33 Commits

Author SHA1 Message Date
a03bb5e7aa pretty JSON formatting 2024-06-21 20:54:47 +04:00
c207c9142d add UnityDependencyContainer implementation of IDependencyContainer 2024-06-21 01:47:51 +04:00
662f9f18d3 replace ServiceProvider with DependencyManager in Forms 2024-06-21 01:42:06 +04:00
20cf8869fa change ServiceProvider to DependencyManager in Program.cs 2024-06-21 01:31:35 +04:00
1adb6bb874 implement CreateBackup in MainForm 2024-06-21 01:06:04 +04:00
69e0aa3313 ListImplement 2024-04-20 23:21:53 +04:00
71e0aec32b FileImplement extension 2024-04-20 23:06:11 +04:00
54f300251d Dynamic dependency loading 2024-04-20 22:45:14 +04:00
d509fd016f fixed ViewModels 2024-04-20 22:08:14 +04:00
e827e57c6b Grid configuring in forms 2024-04-20 21:31:20 +04:00
44548da8de Set ViewModel attributes 2024-04-20 21:08:46 +04:00
cfd78033b2 Search client by login 2024-04-20 19:08:51 +04:00
7ff81c6bbd MailWorker Singleton fix 2024-04-20 19:02:55 +04:00
ae8a20a5bb ListImplement and FileImplement 2024-04-20 00:09:57 +04:00
5b1e3e6d58 Update migration 2024-04-19 23:55:01 +04:00
2ed258e3b8 Edit Program.cs 2024-04-19 23:46:09 +04:00
2a2d3d1845 Forms 2024-04-19 23:21:23 +04:00
14aeac885b Messages BusinessLogic 2024-04-19 23:13:19 +04:00
505a708ddf Messages DatabaseImplement 2024-04-19 22:47:28 +04:00
a5df68d9df ClientApp Mails view 2024-04-19 21:41:12 +04:00
0b7edbd7a0 RestApi ClientController 2024-04-19 21:34:16 +04:00
6581e26f7f MailWorker 2024-04-19 21:10:18 +04:00
f07e32804d MessageInfo DataModels, Contracts 2024-04-19 20:32:50 +04:00
c1a7d73d39 delete PDF-file 2024-04-17 10:01:10 +04:00
da4f49e290 fix WorkerWorkAsync 2024-04-16 23:48:41 +04:00
1b016cc7d8 remove buttons from MainForm 2024-04-16 21:38:14 +04:00
26eadb9fd4 Implementer forms 2024-04-16 21:33:18 +04:00
915758fdf0 update Migration 2024-04-16 20:11:17 +04:00
e3721f13cb DatabaseImplement 2024-04-16 20:08:06 +04:00
3a5157069b add ImplementerController 2024-04-16 19:54:51 +04:00
6700d24634 ListImplement 2024-04-16 19:50:39 +04:00
1e49ce1e21 FileImplement 2024-04-16 00:32:20 +04:00
75911262ea Implementer contracts, data models, business logic 2024-04-16 00:06:12 +04:00
114 changed files with 4655 additions and 687 deletions

4
.gitignore vendored
View File

@@ -398,3 +398,7 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
# AutoWorkshop assemblies
ImplementationExtensions/*.dll

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

@@ -0,0 +1,102 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopDataModels.Models;
using Microsoft.Extensions.Logging;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.Serialization.Json;
namespace AutoWorkshopBusinessLogic.BusinessLogics
{
public class BackUpLogic : IBackUpLogic
{
private readonly ILogger _logger;
private readonly IBackUpInfo _backUpInfo;
public BackUpLogic(ILogger<BackUpLogic> Logger, IBackUpInfo BackUpInfo)
{
_logger = Logger;
_backUpInfo = BackUpInfo;
}
public void CreateBackUp(BackUpSaveBindingModel Model)
{
if (_backUpInfo == null)
return;
try
{
_logger.LogDebug("Clear folder");
var DirInfo = new DirectoryInfo(Model.FolderName);
if (DirInfo.Exists)
{
foreach (var File in DirInfo.GetFiles())
{
File.Delete();
}
}
_logger.LogDebug("Delete archive");
string FileName = $"{Model.FolderName}.zip";
if (File.Exists(FileName))
{
File.Delete(FileName);
}
_logger.LogDebug("Get assembly");
var TypeIId = typeof(IId);
var Assembly = TypeIId.Assembly;
if (Assembly == null)
{
throw new ArgumentNullException("Сборка не найдена", nameof(Assembly));
}
var Types = Assembly.GetTypes();
var Method = GetType().GetMethod("SaveToFile", BindingFlags.NonPublic | BindingFlags.Instance);
_logger.LogDebug("Found {count} types", Types.Length);
foreach (var Type in Types)
{
if (Type.IsInterface && Type.GetInterface(TypeIId.Name) != null)
{
var ModelType = _backUpInfo.GetTypeByModelInterface(Type.Name);
if (ModelType == null)
{
throw new InvalidOperationException($"Не найден класс - модель для { Type.Name }");
}
_logger.LogDebug("Call SaveToFile method for {name} Type", Type.Name);
Method?.MakeGenericMethod(ModelType).Invoke(this, new object[] { Model.FolderName });
}
}
_logger.LogDebug("Create zip and remove folder");
ZipFile.CreateFromDirectory(Model.FolderName, FileName);
DirInfo.Delete(true);
}
catch (Exception)
{
throw;
}
}
private void SaveToFile<T>(string FolderName) where T : class, new()
{
var Records = _backUpInfo.GetList<T>();
if (Records == null)
{
_logger.LogWarning("{type} type get null list", typeof(T).Name);
return;
}
var JsonFormatter = new DataContractJsonSerializer(typeof(List<T>));
using var fs = new FileStream(string.Format("{0}/{1}.json", FolderName, typeof(T).Name), FileMode.OpenOrCreate);
using var writer = JsonReaderWriterFactory.CreateJsonWriter(fs, System.Text.Encoding.UTF8, false, true);
JsonFormatter.WriteObject(writer, Records);
}
}
}

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,135 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicsContracts;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using Microsoft.Extensions.Logging;
namespace AutoWorkshopBusinessLogic.BusinessLogics
{
public class ImplementerLogic : IImplementerLogic
{
private readonly ILogger _logger;
private readonly IImplementerStorage _implementerStorage;
public ImplementerLogic(ILogger<IImplementerLogic> Logger, IImplementerStorage ImplementerStorage)
{
_logger = Logger;
_implementerStorage = ImplementerStorage;
}
public List<ImplementerViewModel>? ReadList(ImplementerSearchModel? Model)
{
_logger.LogInformation("ReadList. ImplementerFIO: {ImplementerFIO}. Password: {Password}. Id: {Id}",
Model?.ImplementerFIO, Model?.Password?.Length, Model?.Id);
var List = Model == null ? _implementerStorage.GetFullList() : _implementerStorage.GetFilteredList(Model);
if (List == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count: {Count}", List.Count);
return List;
}
public ImplementerViewModel? ReadElement(ImplementerSearchModel Model)
{
if (Model is null)
{
throw new ArgumentNullException(nameof(Model));
}
_logger.LogInformation("ReadElement. ImplementerFIO: {ImplementerFIO}. Password: {Password}. Id: {Id}",
Model?.ImplementerFIO, Model?.Password?.Length, Model?.Id);
var Element = _implementerStorage.GetElement(Model);
if (Element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id: {Id}", Element.Id);
return Element;
}
public bool Create(ImplementerBindingModel Model)
{
CheckModel(Model);
if (_implementerStorage.Insert(Model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Update(ImplementerBindingModel Model)
{
CheckModel(Model);
if (_implementerStorage.Update(Model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
public bool Delete(ImplementerBindingModel Model)
{
CheckModel(Model, false);
_logger.LogInformation("Delete. Id:{Id}", Model.Id);
if (_implementerStorage.Delete(Model) == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
private void CheckModel(ImplementerBindingModel Model, bool WithParams = true)
{
if (Model == null)
throw new ArgumentNullException(nameof(Model));
if (!WithParams)
return;
if (string.IsNullOrEmpty(Model.ImplementerFIO))
throw new ArgumentNullException("Нет ФИО исполнителя", nameof(Model.ImplementerFIO));
if (string.IsNullOrEmpty(Model.Password))
throw new ArgumentNullException("Нет пароля исполнителя", nameof(Model.Password));
if (Model.WorkExperience < 0)
throw new ArgumentNullException("Стаж должен быть неотрицательным целым числом", nameof(Model.WorkExperience));
if (Model.Qualification < 0)
throw new ArgumentNullException("Квалификация должна быть неотрицательным целым числом", nameof(Model.Qualification));
_logger.LogInformation("Implementer. ImplementerFIO: {ImplementerFIO}. Password: {Password}. WorkExperience: {WorkExperience}. Qualification: {Qualification}. Id: {Id}",
Model.ImplementerFIO, Model.Password, Model.WorkExperience, Model.Qualification, Model.Id);
var Implementer = _implementerStorage.GetElement(new ImplementerSearchModel
{
ImplementerFIO = Model.ImplementerFIO
});
if (Implementer != null && Implementer.Id != Model.Id)
{
throw new InvalidOperationException("Исполнитель с таким ФИО уже есть");
}
}
}
}

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,33 +9,38 @@ using Microsoft.Extensions.Logging;
namespace AutoWorkshopBusinessLogic.BusinessLogics
{
public class OrderLogic : IOrderLogic
public class OrderLogic : IOrderLogic
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
public OrderLogic(ILogger<RepairLogic> Logger, IOrderStorage OrderStorage)
private readonly AbstractMailWorker _mailLogic;
static readonly object _locker = new object();
public OrderLogic(ILogger<RepairLogic> Logger, IOrderStorage OrderStorage, AbstractMailWorker MailLogic)
{
_logger = Logger;
_orderStorage = OrderStorage;
_mailLogic = MailLogic;
}
public List<OrderViewModel>? ReadList(OrderSearchModel? Model)
{
_logger.LogInformation("ReadList. Id:{Id}", Model?.Id);
_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);
var List = Model is null ? _orderStorage.GetFullList() : _orderStorage.GetFilteredList(Model);
if (List is null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count: {Count}", List.Count);
return List;
}
public bool CreateOrder(OrderBindingModel Model)
{
CheckModel(Model);
@@ -47,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;
}
@@ -76,6 +89,8 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
}
Model.RepairId = Order.RepairId;
Model.ClientId = Order.ClientId;
if (!Model.ImplementerId.HasValue) Model.ImplementerId = Order.ImplementerId;
Model.Count = Order.Count;
Model.Sum = Order.Sum;
Model.DateCreate = Order.DateCreate;
@@ -89,15 +104,26 @@ 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)
{
return ChangeOrderStatus(Model, OrderStatus.BeingProcessed);
lock (_locker)
{
return ChangeOrderStatus(Model, OrderStatus.BeingProcessed);
}
}
public bool FinishOrder(OrderBindingModel Model)
@@ -129,5 +155,27 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
Model.RepairId, Model.Count, Model.Sum, Model.Status, Model.DateCreate,
Model.DateImplement, Model.Id);
}
public OrderViewModel? ReadElement(OrderSearchModel Model)
{
if (Model == null)
{
throw new ArgumentNullException(nameof(Model));
}
_logger.LogInformation("ReadElement. ClientId: {ClientId}. Status: {Status}. ImplementerId: {ImplementerId}. DateFrom: {DateFrom}. DateTo: {DateTo}. OrderId: {Id}",
Model.ClientId, Model.Status, Model.ImplementerId, Model.DateFrom, Model.DateTo, Model.Id);
var Order = _orderStorage.GetElement(Model);
if (Order == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id: {Id}", Order.Id);
return Order;
}
}
}

View File

@@ -0,0 +1,153 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.BusinessLogicsContracts;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Enums;
using Microsoft.Extensions.Logging;
namespace AutoWorkshopBusinessLogic.BusinessLogics
{
public class WorkModeling : IWorkProcess
{
private readonly ILogger _logger;
private readonly Random _rnd;
private IOrderLogic? _orderLogic;
public WorkModeling(ILogger<WorkModeling> Logger)
{
_logger = Logger;
_rnd = new Random(1000);
}
public void DoWork(IImplementerLogic ImplementerLogic, IOrderLogic OrderLogic)
{
_orderLogic = OrderLogic;
var Implementers = ImplementerLogic.ReadList(null);
if (Implementers == null)
{
_logger.LogWarning("DoWork. Implementers is null");
return;
}
var Orders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Accepted });
var BeingProcessedOrders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.BeingProcessed });
// in case there are BeingProcessed orders but no Accepted orders
if (Orders == null || BeingProcessedOrders == null || (Orders.Count == 0 && BeingProcessedOrders.Count == 0))
{
_logger.LogWarning("DoWork. Orders is null or empty");
return;
}
_logger.LogDebug("DoWork for {Count} orders", Orders.Count);
foreach (var Implementer in Implementers)
{
Task.Run(() => WorkerWorkAsync(Implementer, Orders));
}
}
private async Task WorkerWorkAsync(ImplementerViewModel Implementer, List<OrderViewModel> Orders)
{
if (_orderLogic == null || Implementer == null)
{
return;
}
await RunOrderInWork(Implementer);
await Task.Run(() =>
{
foreach (var Order in Orders)
{
try
{
_logger.LogDebug("WorkerWorkAsync. Worker {Id} try get order {Order}", Implementer.Id, Order.Id);
// TakeOrderInWork will fail when the worker tries to change status to BeingProcessed when the order is already BeingProcessed
// which would happen when other worker already acquired that order
bool AcquireResult = _orderLogic.TakeOrderInWork(new OrderBindingModel
{
Id = Order.Id,
ImplementerId = Implementer.Id
});
if (!AcquireResult)
{
_logger.LogDebug("WorkerWorkAsync. Worker {Id} tried to get order {Order} but it's already acquired by other worker", Implementer.Id, Order.Id);
continue;
}
Thread.Sleep(Implementer.WorkExperience * _rnd.Next(100, 1000) * Order.Count);
_logger.LogDebug("WorkerWorkAsync. Worker {Id} finish order {Order}", Implementer.Id, Order.Id);
_orderLogic.FinishOrder(new OrderBindingModel
{
Id = Order.Id
});
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Error try get work");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while do work");
throw;
}
Thread.Sleep(Implementer.Qualification * _rnd.Next(10, 100));
}
});
}
private async Task RunOrderInWork(ImplementerViewModel Implementer)
{
if (_orderLogic == null || Implementer == null)
return;
try
{
var RunOrder = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel
{
ImplementerId = Implementer.Id,
Status = OrderStatus.BeingProcessed
}));
if (RunOrder == null)
{
return;
}
_logger.LogDebug("RunOrderInWork. Worker {Id} back to order {Order}", Implementer.Id, RunOrder.Id);
Thread.Sleep(Implementer.WorkExperience * _rnd.Next(100, 300) * RunOrder.Count);
_logger.LogDebug("RunOrderInWork. Worker {Id} finish order {Order}", Implementer.Id, RunOrder.Id);
_orderLogic.FinishOrder(new OrderBindingModel
{
Id = RunOrder.Id
});
Thread.Sleep(Implementer.Qualification * _rnd.Next(10, 100));
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Error try get work");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while do work");
throw;
}
}
}
}

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,26 @@
namespace AutoWorkshopContracts.Attrubites
{
[AttributeUsage(AttributeTargets.Property)]
public class ColumnAttribute : Attribute
{
public ColumnAttribute(string Title = "", bool Visible = true, int Width = 0,
GridViewAutoSize GridViewAutoSize = GridViewAutoSize.None, bool IsUseAutoSize = false)
{
this.Title = Title;
this.Visible = Visible;
this.Width = Width;
this.GridViewAutoSize = GridViewAutoSize;
this.IsUseAutoSize = IsUseAutoSize;
}
public string Title { get; private set; }
public bool Visible { get; private set; }
public int Width { get; private set; }
public GridViewAutoSize GridViewAutoSize { get; private set; }
public bool IsUseAutoSize { get; private set; }
}
}

View File

@@ -0,0 +1,14 @@
namespace AutoWorkshopContracts.Attrubites
{
public enum GridViewAutoSize
{
NotSet = 0,
None = 1,
ColumnHeader = 2,
AllCellsExceptHeader = 4,
AllCells = 6,
DisplayedCellsExceptHeader = 8,
DisplayedCells = 10,
Fill = 16
}
}

View File

@@ -6,6 +6,13 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Unity" Version="5.11.10" />
<PackageReference Include="Unity.Microsoft.Logging" Version="5.11.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AutoWorkshopDataModels\AutoWorkshopDataModels.csproj" />
</ItemGroup>

View File

@@ -0,0 +1,7 @@
namespace AutoWorkshopContracts.BindingModels
{
public class BackUpSaveBindingModel
{
public string FolderName { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,17 @@
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.BindingModels
{
public class ImplementerBindingModel : IImplementerModel
{
public int Id { get; set; }
public string ImplementerFIO { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public int WorkExperience { get; set; }
public int Qualification { get; set; }
}
}

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,21 @@
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.BindingModels
{
public class MessageInfoBindingModel : IMessageInfoModel
{
public int Id { get; set; }
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

@@ -8,6 +8,7 @@ namespace AutoWorkshopContracts.BindingModels
public int Id { get; set; }
public int RepairId { get; set; }
public int ClientId { get; set; }
public int? ImplementerId { get; set; }
public int Count { get; set; }
public double Sum { get; set; }
public OrderStatus Status { get; set; } = OrderStatus.Undefined;

View File

@@ -0,0 +1,9 @@
using AutoWorkshopContracts.BindingModels;
namespace AutoWorkshopContracts.BusinessLogicContracts
{
public interface IBackUpLogic
{
void CreateBackUp(BackUpSaveBindingModel Model);
}
}

View File

@@ -0,0 +1,19 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.ViewModels;
namespace AutoWorkshopContracts.BusinessLogicsContracts
{
public interface IImplementerLogic
{
List<ImplementerViewModel>? ReadList(ImplementerSearchModel? Model);
ImplementerViewModel? ReadElement(ImplementerSearchModel Model);
bool Create(ImplementerBindingModel Model);
bool Update(ImplementerBindingModel Model);
bool Delete(ImplementerBindingModel Model);
}
}

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

@@ -11,5 +11,6 @@ namespace AutoWorkshopContracts.BusinessLogicContracts
bool TakeOrderInWork(OrderBindingModel Model);
bool FinishOrder(OrderBindingModel Model);
bool DeliveryOrder(OrderBindingModel Model);
OrderViewModel? ReadElement(OrderSearchModel Model);
}
}

View File

@@ -0,0 +1,9 @@
using AutoWorkshopContracts.BusinessLogicsContracts;
namespace AutoWorkshopContracts.BusinessLogicContracts
{
public interface IWorkProcess
{
void DoWork(IImplementerLogic ImplementerLogic, IOrderLogic OrderLogic);
}
}

View File

@@ -0,0 +1,48 @@
using Microsoft.Extensions.Logging;
namespace AutoWorkshopContracts.DI
{
public class DependencyManager
{
private readonly IDependencyContainer _dependencyContainer;
private static DependencyManager? _manager;
private static readonly object _lock = new();
private DependencyManager()
{
_dependencyContainer = new ServiceDependencyContainer();
}
public static DependencyManager Instance
{
get
{
if (_manager == null)
{
lock (_lock) { _manager = new DependencyManager(); }
}
return _manager;
}
}
public static void InitDependency()
{
var Ext = ServiceProviderLoader.GetImplementationExtension();
if (Ext == null)
{
throw new ArgumentNullException("Отсутствуют компоненты для загрузки зависимостей по модулям");
}
Ext.RegisterServices();
}
public void AddLogging(Action<ILoggingBuilder> Configure) => _dependencyContainer.AddLogging(Configure);
public void RegisterType<T, U>(bool IsSingleton = false) where U : class, T where T : class => _dependencyContainer.RegisterType<T, U>(IsSingleton);
public void RegisterType<T>(bool IsSingleton = false) where T : class => _dependencyContainer.RegisterType<T>(IsSingleton);
public T Resolve<T>() => _dependencyContainer.Resolve<T>();
}
}

View File

@@ -0,0 +1,15 @@
using Microsoft.Extensions.Logging;
namespace AutoWorkshopContracts.DI
{
public interface IDependencyContainer
{
void AddLogging(Action<ILoggingBuilder> Configure);
void RegisterType<T, U>(bool IsSingleton) where U : class, T where T : class;
void RegisterType<T>(bool IsSingleton) where T : class;
T Resolve<T>();
}
}

View File

@@ -0,0 +1,9 @@
namespace AutoWorkshopContracts.DI
{
public interface IImplementationExtension
{
public int Priority { get; }
public void RegisterServices();
}
}

View File

@@ -0,0 +1,59 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace AutoWorkshopContracts.DI
{
public class ServiceDependencyContainer : IDependencyContainer
{
private ServiceProvider? _serviceProvider;
private readonly ServiceCollection _serviceCollection;
public ServiceDependencyContainer()
{
_serviceCollection = new ServiceCollection();
}
public void AddLogging(Action<ILoggingBuilder> Configure)
{
_serviceCollection.AddLogging(Configure);
}
public void RegisterType<T, U>(bool IsSingleton) where U : class, T where T : class
{
if (IsSingleton)
{
_serviceCollection.AddSingleton<T, U>();
}
else
{
_serviceCollection.AddTransient<T, U>();
}
_serviceProvider = null;
}
public void RegisterType<T>(bool IsSingleton) where T : class
{
if (IsSingleton)
{
_serviceCollection.AddSingleton<T>();
}
else
{
_serviceCollection.AddTransient<T>();
}
_serviceProvider = null;
}
public T Resolve<T>()
{
if (_serviceProvider == null)
{
_serviceProvider = _serviceCollection.BuildServiceProvider();
}
return _serviceProvider.GetService<T>()!;
}
}
}

View File

@@ -0,0 +1,50 @@
using System.Reflection;
namespace AutoWorkshopContracts.DI
{
public static class ServiceProviderLoader
{
public static IImplementationExtension? GetImplementationExtension()
{
IImplementationExtension? Source = null;
var Files = Directory.GetFiles(TryGetImplementationExtensionsFolder(), "*.dll", SearchOption.AllDirectories);
foreach (var File in Files.Distinct())
{
Assembly Asm = Assembly.LoadFrom(File);
foreach (var Type in Asm.GetExportedTypes())
{
if (Type.IsClass && typeof(IImplementationExtension).IsAssignableFrom(Type))
{
if (Source == null)
{
Source = (IImplementationExtension)Activator.CreateInstance(Type)!;
}
else
{
var NewSource = (IImplementationExtension)Activator.CreateInstance(Type)!;
if (NewSource.Priority > Source.Priority)
{
Source = NewSource;
}
}
}
}
}
return Source;
}
private static string TryGetImplementationExtensionsFolder()
{
var WorkingDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
while (WorkingDirectory != null && !WorkingDirectory.GetDirectories("ImplementationExtensions", SearchOption.AllDirectories).Any(x => x.Name == "ImplementationExtensions"))
{
WorkingDirectory = WorkingDirectory.Parent;
}
return $"{WorkingDirectory?.FullName}\\ImplementationExtensions";
}
}
}

View File

@@ -0,0 +1,38 @@
using Microsoft.Extensions.Logging;
using Unity;
using Unity.Microsoft.Logging;
namespace AutoWorkshopContracts.DI
{
public class UnityDependencyContainer : IDependencyContainer
{
private readonly IUnityContainer _container;
public UnityDependencyContainer()
{
_container = new UnityContainer();
}
public void AddLogging(Action<ILoggingBuilder> Configure)
{
var Factory = LoggerFactory.Create(Configure);
_container.AddExtension(new LoggingExtension(Factory));
}
public void RegisterType<T>(bool IsSingleton) where T : class
{
_container.RegisterType<T>(IsSingleton ? TypeLifetime.Singleton : TypeLifetime.Transient);
}
public T Resolve<T>()
{
return _container.Resolve<T>();
}
void IDependencyContainer.RegisterType<T, U>(bool IsSingleton)
{
_container.RegisterType<T, U>(IsSingleton ? TypeLifetime.Singleton : TypeLifetime.Transient);
}
}
}

View File

@@ -0,0 +1,11 @@
namespace AutoWorkshopContracts.SearchModels
{
public class ImplementerSearchModel
{
public int? Id { get; set; }
public string? ImplementerFIO { get; set; }
public string? Password { get; set; }
}
}

View File

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

View File

@@ -1,4 +1,6 @@
namespace AutoWorkshopContracts.SearchModels
using AutoWorkshopDataModels.Enums;
namespace AutoWorkshopContracts.SearchModels
{
public class OrderSearchModel
{
@@ -6,6 +8,10 @@
public int? ClientId { get; set; }
public OrderStatus? Status { get; set; }
public int? ImplementerId { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }

View File

@@ -0,0 +1,9 @@
namespace AutoWorkshopContracts.StoragesContracts
{
public interface IBackUpInfo
{
List<T>? GetList<T>() where T : class, new();
Type? GetTypeByModelInterface(string ModelInterfaceName);
}
}

View File

@@ -0,0 +1,21 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.ViewModels;
namespace AutoWorkshopContracts.StoragesContracts
{
public interface IImplementerStorage
{
List<ImplementerViewModel> GetFullList();
List<ImplementerViewModel> GetFilteredList(ImplementerSearchModel Model);
ImplementerViewModel? GetElement(ImplementerSearchModel Model);
ImplementerViewModel? Insert(ImplementerBindingModel Model);
ImplementerViewModel? Update(ImplementerBindingModel Model);
ImplementerViewModel? Delete(ImplementerBindingModel Model);
}
}

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

@@ -1,19 +1,20 @@
using AutoWorkshopDataModels.Models;
using System.ComponentModel;
using AutoWorkshopContracts.Attrubites;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.ViewModels
{
public class ClientViewModel : IClientModel
public class ClientViewModel : IClientModel
{
public int Id { get; set; }
[Column(Visible: false)]
public int Id { get; set; }
[Column(Title: "ФИО клиента", Width: 150)]
public string ClientFIO { get; set; } = string.Empty;
[DisplayName("ФИО клиента")]
public string ClientFIO { get; set; } = string.Empty;
[DisplayName("Логин (эл. почта)")]
public string Email { get; set; } = string.Empty;
[DisplayName("Пароль")]
public string Password { get; set; } = string.Empty;
[Column(Title: "Логин (эл. почта)", GridViewAutoSize: GridViewAutoSize.Fill, IsUseAutoSize: true)]
public string Email { get; set; } = string.Empty;
[Column(Title: "Пароль", Width: 150)]
public string Password { get; set; } = string.Empty;
}
}

View File

@@ -1,16 +1,17 @@
using AutoWorkshopDataModels.Models;
using System.ComponentModel;
using AutoWorkshopContracts.Attrubites;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.ViewModels
{
public class ComponentViewModel : IComponentModel
public class ComponentViewModel : IComponentModel
{
public int Id { get; set; }
[Column(Visible: false)]
public int Id { get; set; }
[DisplayName("Название компонента")]
public string ComponentName { get; set; } = string.Empty;
[DisplayName("Цена")]
public double Cost { get; set; }
[Column(Title: "Название компонента", GridViewAutoSize: GridViewAutoSize.Fill, IsUseAutoSize: true)]
public string ComponentName { get; set; } = string.Empty;
[Column(Title: "Цена", Width: 150)]
public double Cost { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using AutoWorkshopContracts.Attrubites;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.ViewModels
{
public class ImplementerViewModel : IImplementerModel
{
[Column(Visible: false)]
public int Id { get; set; }
[Column(Title: "ФИО исполнителя", GridViewAutoSize: GridViewAutoSize.AllCells, IsUseAutoSize: true)]
public string ImplementerFIO { get; set; } = string.Empty;
[Column(Title: "Пароль", Width: 100)]
public string Password { get; set; } = string.Empty;
[Column(Title: "Стаж работы", GridViewAutoSize: GridViewAutoSize.Fill, IsUseAutoSize: true)]
public int WorkExperience { get; set; }
[Column(Title: "Квалификация", GridViewAutoSize: GridViewAutoSize.Fill, IsUseAutoSize: true)]
public int Qualification { get; set; }
}
}

View File

@@ -0,0 +1,29 @@
using AutoWorkshopContracts.Attrubites;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.ViewModels
{
public class MessageInfoViewModel : IMessageInfoModel
{
[Column(Visible: false)]
public int Id { get; set; }
[Column(Visible: false)]
public string MessageId { get; set; } = string.Empty;
[Column(Visible: false)]
public int? ClientId { get; set; }
[Column(Title: "Отправитель", Width: 150)]
public string SenderName { get; set; } = string.Empty;
[Column(Title: "Дата доставки", Width: 120)]
public DateTime DateDelivery { get; set; }
[Column(Title: "Тема", Width: 120)]
public string Subject { get; set; } = string.Empty;
[Column(Title: "Содержание", GridViewAutoSize: GridViewAutoSize.Fill, IsUseAutoSize: true)]
public string Body { get; set; } = string.Empty;
}
}

View File

@@ -1,37 +1,48 @@
using AutoWorkshopDataModels.Enums;
using AutoWorkshopContracts.Attrubites;
using AutoWorkshopDataModels.Enums;
using AutoWorkshopDataModels.Models;
using System.ComponentModel;
namespace AutoWorkshopContracts.ViewModels
{
public class OrderViewModel : IOrderModel
public class OrderViewModel : IOrderModel
{
[DisplayName("Номер")]
public int Id { get; set; }
public int RepairId { get; set; }
[Column(Title: "Номер", GridViewAutoSize: GridViewAutoSize.AllCells, IsUseAutoSize: true)]
public int Id { get; set; }
[DisplayName("Ремонт")]
public string RepairName { get; set; } = string.Empty;
[Column(Visible: false)]
public int RepairId { get; set; }
public int ClientId { get; set; }
[DisplayName("Клиент")]
public string ClientFIO { get; set; } = string.Empty;
[Column(Title: "Ремонт", GridViewAutoSize: GridViewAutoSize.AllCells, IsUseAutoSize: true)]
public string RepairName { get; set; } = string.Empty;
[DisplayName("Количество")]
public int Count { get; set; }
[DisplayName("Сумма")]
public double Sum { get; set; }
[DisplayName("Статус")]
public OrderStatus Status { get; set; } = OrderStatus.Undefined;
[DisplayName("Дата создания")]
public DateTime DateCreate { get; set; } = DateTime.Now;
[DisplayName("Дата выполнения")]
public DateTime? DateImplement { get; set; }
[Column(Visible: false)]
public int ClientId { get; set; }
[Column(Title: "Клиент", Width: 120)]
public string ClientFIO { get; set; } = string.Empty;
[Column(Title: "Почта клиента", Width: 190)]
public string ClientEmail { get; set; } = string.Empty;
[Column(Visible: false)]
public int? ImplementerId { get; set; }
[Column(Title: "Исполнитель", Width: 120)]
public string? ImplementerFIO { get; set; }
[Column(Title: "Количество", Width: 100)]
public int Count { get; set; }
[Column(Title: "Сумма", Width: 75)]
public double Sum { get; set; }
[Column(Title: "Статус", Width: 70)]
public OrderStatus Status { get; set; } = OrderStatus.Undefined;
[Column(Title: "Дата создания", Width: 120)]
public DateTime DateCreate { get; set; } = DateTime.Now;
[Column(Title: "Дата выполнения", Width: 120)]
public DateTime? DateImplement { get; set; }
}
}

View File

@@ -1,22 +1,20 @@
using AutoWorkshopDataModels.Models;
using System.ComponentModel;
using AutoWorkshopContracts.Attrubites;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.ViewModels
{
public class RepairViewModel : IRepairModel
public class RepairViewModel : IRepairModel
{
public int Id { get; set; }
[Column(Visible: false)]
public int Id { get; set; }
[DisplayName("Название ремонта")]
public string RepairName { get; set; } = string.Empty;
[Column(Title: "Название ремонта", GridViewAutoSize: GridViewAutoSize.Fill, IsUseAutoSize: true)]
public string RepairName { get; set; } = string.Empty;
[DisplayName("Цена")]
public double Price { get; set; }
public Dictionary<int, (IComponentModel, int)> RepairComponents
{
get;
set;
} = new();
[Column(Title: "Цена", Width: 70)]
public double Price { get; set; }
[Column(Visible: false)]
public Dictionary<int, (IComponentModel, int)> RepairComponents { get; set; } = new();
}
}

View File

@@ -0,0 +1,13 @@
namespace AutoWorkshopDataModels.Models
{
public interface IImplementerModel : IId
{
string ImplementerFIO { get; }
string Password { get; }
int WorkExperience { get; }
int Qualification { get; }
}
}

View File

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

View File

@@ -6,6 +6,7 @@ namespace AutoWorkshopDataModels.Models
{
int RepairId { get; }
int ClientId { get; }
int? ImplementerId { get; }
int Count { get; }
double Sum { get; }
OrderStatus Status { get; }

View File

@@ -9,7 +9,7 @@ namespace AutoWorkshopDatabaseImplement
{
if (OptionsBuilder.IsConfigured == false)
{
OptionsBuilder.UseNpgsql(@"Host=localhost;Database=AutoWorkshop;Username=postgres;Password=admin");
OptionsBuilder.UseNpgsql(@"Host=localhost;Database=AutoWorkshop;Port=5000;Username=postgres;Password=admin");
}
base.OnConfiguring(OptionsBuilder);
@@ -27,5 +27,9 @@ namespace AutoWorkshopDatabaseImplement
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

@@ -21,4 +21,8 @@
<ProjectReference Include="..\AutoWorkshopDataModels\AutoWorkshopDataModels.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy /Y &quot;$(TargetDir)*.dll&quot; &quot;$(SolutionDir)ImplementationExtensions\*.dll&quot;" />
</Target>
</Project>

View File

@@ -0,0 +1,22 @@
using AutoWorkshopContracts.DI;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopDatabaseImplement.Implements;
namespace AutoWorkshopDatabaseImplement
{
public class ImplementationExtension : IImplementationExtension
{
public int Priority => 2;
public void RegisterServices()
{
DependencyManager.Instance.RegisterType<IClientStorage, ClientStorage>();
DependencyManager.Instance.RegisterType<IComponentStorage, ComponentStorage>();
DependencyManager.Instance.RegisterType<IImplementerStorage, ImplementerStorage>();
DependencyManager.Instance.RegisterType<IMessageInfoStorage, MessageInfoStorage>();
DependencyManager.Instance.RegisterType<IOrderStorage, OrderStorage>();
DependencyManager.Instance.RegisterType<IRepairStorage, RepairStorage>();
DependencyManager.Instance.RegisterType<IBackUpInfo, BackUpInfo>();
}
}
}

View File

@@ -0,0 +1,29 @@
using AutoWorkshopContracts.StoragesContracts;
namespace AutoWorkshopDatabaseImplement.Implements
{
public class BackUpInfo : IBackUpInfo
{
public List<T>? GetList<T>() where T : class, new()
{
using var Context = new AutoWorkshopDatabase();
return Context.Set<T>().ToList();
}
public Type? GetTypeByModelInterface(string ModelInterfaceName)
{
var Assembly = typeof(BackUpInfo).Assembly;
var Types = Assembly.GetTypes();
foreach (var Type in Types)
{
if (Type.IsClass && Type.GetInterface(ModelInterfaceName) != null)
{
return Type;
}
}
return null;
}
}
}

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,90 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDatabaseImplement.Models;
namespace AutoWorkshopDatabaseImplement.Implements
{
public class ImplementerStorage : IImplementerStorage
{
public List<ImplementerViewModel> GetFullList()
{
using var Context = new AutoWorkshopDatabase();
return Context.Implementers.Select(x => x.GetViewModel).ToList();
}
public List<ImplementerViewModel> GetFilteredList(ImplementerSearchModel Model)
{
if (string.IsNullOrEmpty(Model.ImplementerFIO))
{
return new();
}
using var Context = new AutoWorkshopDatabase();
return Context.Implementers.Where(x => x.ImplementerFIO.Contains(Model.ImplementerFIO)).Select(x => x.GetViewModel).ToList();
}
public ImplementerViewModel? GetElement(ImplementerSearchModel Model)
{
if (string.IsNullOrEmpty(Model.ImplementerFIO) && !Model.Id.HasValue)
{
return null;
}
using var Context = new AutoWorkshopDatabase();
return Context.Implementers.FirstOrDefault(x =>
(!string.IsNullOrEmpty(Model.ImplementerFIO) && x.ImplementerFIO == Model.ImplementerFIO && (!string.IsNullOrEmpty(Model.Password) ? x.Password == Model.Password : true)) ||
(Model.Id.HasValue && x.Id == Model.Id))
?.GetViewModel;
}
public ImplementerViewModel? Insert(ImplementerBindingModel Model)
{
var NewImplementer = Implementer.Create(Model);
if (NewImplementer == null)
{
return null;
}
using var Context = new AutoWorkshopDatabase();
Context.Implementers.Add(NewImplementer);
Context.SaveChanges();
return NewImplementer.GetViewModel;
}
public ImplementerViewModel? Update(ImplementerBindingModel Model)
{
using var Context = new AutoWorkshopDatabase();
var Implementer = Context.Implementers.FirstOrDefault(x => x.Id == Model.Id);
if (Implementer == null)
{
return null;
}
Implementer.Update(Model);
Context.SaveChanges();
return Implementer.GetViewModel;
}
public ImplementerViewModel? Delete(ImplementerBindingModel Model)
{
using var Context = new AutoWorkshopDatabase();
var Implementer = Context.Implementers.FirstOrDefault(rec => rec.Id == Model.Id);
if (Implementer == null)
{
return null;
}
Context.Implementers.Remove(Implementer);
Context.SaveChanges();
return Implementer.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

@@ -16,6 +16,7 @@ namespace AutoWorkshopDatabaseImplement.Implements
return Context.Orders
.Include(x => x.Repair)
.Include(x => x.Client)
.Include(x => x.Implementer)
.Select(x => x.GetViewModel)
.ToList();
}
@@ -29,6 +30,7 @@ namespace AutoWorkshopDatabaseImplement.Implements
return Context.Orders
.Include(x => x.Repair)
.Include(x => x.Client)
.Include(x => x.Implementer)
.Where(x => (x.DateCreate >= Model.DateFrom && x.DateCreate <= Model.DateTo) && (!Model.ClientId.HasValue || x.ClientId == Model.ClientId))
.Select(x => x.GetViewModel)
.ToList();
@@ -37,14 +39,18 @@ namespace AutoWorkshopDatabaseImplement.Implements
return Context.Orders
.Include(x => x.Repair)
.Include(x => x.Client)
.Where(x => (Model.Id.HasValue && x.Id == Model.Id) || (Model.ClientId.HasValue && x.ClientId == Model.ClientId))
.Include (x => x.Implementer)
.Where(x => (Model.Id.HasValue && x.Id == Model.Id)
|| (Model.ClientId.HasValue && x.ClientId == Model.ClientId)
|| (Model.ImplementerId.HasValue && x.ImplementerId == Model.ImplementerId)
|| (Model.Status.HasValue && x.Status == Model.Status))
.Select(x => x.GetViewModel)
.ToList();
}
public OrderViewModel? GetElement(OrderSearchModel Model)
{
if (!Model.Id.HasValue)
if (!Model.Id.HasValue && !Model.ImplementerId.HasValue && !Model.Status.HasValue)
return null;
using var Context = new AutoWorkshopDatabase();
@@ -52,7 +58,9 @@ namespace AutoWorkshopDatabaseImplement.Implements
return Context.Orders
.Include(x => x.Repair)
.Include(x => x.Client)
.FirstOrDefault(x => Model.Id.HasValue && x.Id == Model.Id)?
.Include(x => x.Implementer)
.FirstOrDefault(x => (Model.Id.HasValue && x.Id == Model.Id)
|| (Model.ImplementerId.HasValue && Model.Status.HasValue && x.ImplementerId == Model.ImplementerId && x.Status == Model.Status) )?
.GetViewModel;
}
@@ -70,7 +78,7 @@ namespace AutoWorkshopDatabaseImplement.Implements
Context.Orders.Add(NewOrder);
Context.SaveChanges();
return Context.Orders.Include(x => x.Repair).Include(x => x.Client).FirstOrDefault(x => x.Id == NewOrder.Id)?.GetViewModel;
return Context.Orders.Include(x => x.Repair).Include(x => x.Client).Include(x => x.Implementer).FirstOrDefault(x => x.Id == NewOrder.Id)?.GetViewModel;
}
public OrderViewModel? Update(OrderBindingModel Model)
@@ -84,13 +92,13 @@ namespace AutoWorkshopDatabaseImplement.Implements
Order.Update(Model);
Context.SaveChanges();
return Context.Orders.Include(x => x.Repair).Include(x => x.Client).FirstOrDefault(x => x.Id == Model.Id)?.GetViewModel;
return Context.Orders.Include(x => x.Repair).Include(x => x.Client).Include(x => x.Implementer).FirstOrDefault(x => x.Id == Model.Id)?.GetViewModel;
}
public OrderViewModel? Delete(OrderBindingModel Model)
{
using var Context = new AutoWorkshopDatabase();
var Order = Context.Orders.Include(x => x.Repair).Include(x => x.Client).FirstOrDefault(rec => rec.Id == Model.Id);
var Order = Context.Orders.Include(x => x.Repair).Include(x => x.Client).Include(x => x.Implementer).FirstOrDefault(rec => rec.Id == Model.Id);
if (Order == null)
return null;

View File

@@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace AutoWorkshopDatabaseImplement.Migrations
{
[DbContext(typeof(AutoWorkshopDatabase))]
[Migration("20240411091839_Clients")]
partial class Clients
[Migration("20240419194703_Mails")]
partial class Mails
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -70,6 +70,63 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.ToTable("Components");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Implementer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ImplementerFIO")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Qualification")
.HasColumnType("integer");
b.Property<int>("WorkExperience")
.HasColumnType("integer");
b.HasKey("Id");
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")
@@ -90,6 +147,9 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.Property<DateTime?>("DateImplement")
.HasColumnType("timestamp without time zone");
b.Property<int?>("ImplementerId")
.HasColumnType("integer");
b.Property<int>("RepairId")
.HasColumnType("integer");
@@ -103,6 +163,8 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.HasIndex("ClientId");
b.HasIndex("ImplementerId");
b.HasIndex("RepairId");
b.ToTable("Orders");
@@ -154,14 +216,25 @@ 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();
b.HasOne("AutoWorkshopDatabaseImplement.Models.Implementer", "Implementer")
.WithMany("Order")
.HasForeignKey("ImplementerId");
b.HasOne("AutoWorkshopDatabaseImplement.Models.Repair", "Repair")
.WithMany("Orders")
.HasForeignKey("RepairId")
@@ -170,6 +243,8 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.Navigation("Client");
b.Navigation("Implementer");
b.Navigation("Repair");
});
@@ -194,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 =>
@@ -202,6 +279,11 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.Navigation("RepairComponents");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Order");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Repair", b =>
{
b.Navigation("Components");

View File

@@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace AutoWorkshopDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class Clients : Migration
public partial class Mails : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@@ -41,6 +41,22 @@ namespace AutoWorkshopDatabaseImplement.Migrations
table.PrimaryKey("PK_Components", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Implementers",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ImplementerFIO = table.Column<string>(type: "text", nullable: false),
Password = table.Column<string>(type: "text", nullable: false),
WorkExperience = table.Column<int>(type: "integer", nullable: false),
Qualification = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Implementers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Repairs",
columns: table => new
@@ -55,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
@@ -63,6 +100,7 @@ namespace AutoWorkshopDatabaseImplement.Migrations
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
RepairId = table.Column<int>(type: "integer", nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false),
ImplementerId = table.Column<int>(type: "integer", nullable: true),
Count = table.Column<int>(type: "integer", nullable: false),
Sum = table.Column<double>(type: "double precision", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
@@ -78,6 +116,11 @@ namespace AutoWorkshopDatabaseImplement.Migrations
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Orders_Implementers_ImplementerId",
column: x => x.ImplementerId,
principalTable: "Implementers",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Orders_Repairs_RepairId",
column: x => x.RepairId,
@@ -113,11 +156,21 @@ namespace AutoWorkshopDatabaseImplement.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Messages_ClientId",
table: "Messages",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_Orders_ClientId",
table: "Orders",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_Orders_ImplementerId",
table: "Orders",
column: "ImplementerId");
migrationBuilder.CreateIndex(
name: "IX_Orders_RepairId",
table: "Orders",
@@ -137,6 +190,9 @@ namespace AutoWorkshopDatabaseImplement.Migrations
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Messages");
migrationBuilder.DropTable(
name: "Orders");
@@ -146,6 +202,9 @@ namespace AutoWorkshopDatabaseImplement.Migrations
migrationBuilder.DropTable(
name: "Clients");
migrationBuilder.DropTable(
name: "Implementers");
migrationBuilder.DropTable(
name: "Components");

View File

@@ -67,6 +67,63 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.ToTable("Components");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Implementer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ImplementerFIO")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Qualification")
.HasColumnType("integer");
b.Property<int>("WorkExperience")
.HasColumnType("integer");
b.HasKey("Id");
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")
@@ -87,6 +144,9 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.Property<DateTime?>("DateImplement")
.HasColumnType("timestamp without time zone");
b.Property<int?>("ImplementerId")
.HasColumnType("integer");
b.Property<int>("RepairId")
.HasColumnType("integer");
@@ -100,6 +160,8 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.HasIndex("ClientId");
b.HasIndex("ImplementerId");
b.HasIndex("RepairId");
b.ToTable("Orders");
@@ -151,14 +213,25 @@ 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();
b.HasOne("AutoWorkshopDatabaseImplement.Models.Implementer", "Implementer")
.WithMany("Order")
.HasForeignKey("ImplementerId");
b.HasOne("AutoWorkshopDatabaseImplement.Models.Repair", "Repair")
.WithMany("Orders")
.HasForeignKey("RepairId")
@@ -167,6 +240,8 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.Navigation("Client");
b.Navigation("Implementer");
b.Navigation("Repair");
});
@@ -191,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 =>
@@ -199,6 +276,11 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.Navigation("RepairComponents");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Order");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Repair", b =>
{
b.Navigation("Components");

View File

@@ -3,24 +3,33 @@ using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;
namespace AutoWorkshopDatabaseImplement.Models
{
[DataContract]
public class Client : IClientModel
{
[DataMember]
public int Id { get; private set; }
[Required]
[DataMember]
[Required]
public string ClientFIO { get; private set; } = string.Empty;
[Required]
[DataMember]
[Required]
public string Email { get; set; } = string.Empty;
[Required]
[DataMember]
[Required]
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

@@ -3,17 +3,22 @@ using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;
namespace AutoWorkshopDatabaseImplement.Models
{
[DataContract]
public class Component : IComponentModel
{
[DataMember]
public int Id { get; private set; }
[Required]
[DataMember]
[Required]
public string ComponentName { get; private set; } = string.Empty;
[Required]
[DataMember]
[Required]
public double Cost { get; set; }
[ForeignKey("ComponentId")]

View File

@@ -0,0 +1,71 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;
namespace AutoWorkshopDatabaseImplement.Models
{
[DataContract]
public class Implementer : IImplementerModel
{
[DataMember]
public int Id { get; set; }
[DataMember]
[Required]
public string ImplementerFIO { get; set; } = string.Empty;
[DataMember]
[Required]
public string Password { get; set; } = string.Empty;
[DataMember]
[Required]
public int WorkExperience { get; set; }
[DataMember]
[Required]
public int Qualification { get; set; }
[ForeignKey("ImplementerId")]
public virtual List<Order> Order { get; set; } = new();
public static Implementer? Create(ImplementerBindingModel? Model)
{
if (Model == null)
return null;
return new Implementer()
{
Id = Model.Id,
ImplementerFIO = Model.ImplementerFIO,
Password = Model.Password,
WorkExperience = Model.WorkExperience,
Qualification = Model.Qualification
};
}
public void Update(ImplementerBindingModel Model)
{
if (Model == null)
{
return;
}
ImplementerFIO = Model.ImplementerFIO;
Password = Model.Password;
WorkExperience = Model.WorkExperience;
Qualification = Model.Qualification;
}
public ImplementerViewModel GetViewModel => new()
{
Id = Id,
ImplementerFIO = ImplementerFIO,
Password = Password,
WorkExperience = WorkExperience,
Qualification = Qualification
};
}
}

View File

@@ -0,0 +1,61 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;
namespace AutoWorkshopDatabaseImplement.Models
{
[DataContract]
public class MessageInfo : IMessageInfoModel
{
[NotMapped]
public int Id { get; set; }
[DataMember]
[Key]
public string MessageId { get; set; } = string.Empty;
[DataMember]
public int? ClientId { get; set; }
[DataMember]
public string SenderName { get; set; } = string.Empty;
[DataMember]
public DateTime DateDelivery { get; set; }
[DataMember]
public string Subject { get; set; } = string.Empty;
[DataMember]
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

@@ -3,36 +3,51 @@ using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Enums;
using AutoWorkshopDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace AutoWorkshopDatabaseImplement.Models
{
[DataContract]
public class Order : IOrderModel
{
[DataMember]
public int Id { get; private set; }
[Required]
[DataMember]
[Required]
public int RepairId { get; private set; }
public virtual Repair Repair { get; set; }
[Required]
[DataMember]
[Required]
public int ClientId { get; private set; }
public virtual Client Client { get; set; }
[Required]
[DataMember]
public int? ImplementerId { get; private set; }
public virtual Implementer? Implementer { get; set; }
[DataMember]
[Required]
public int Count { get; private set; }
[Required]
[DataMember]
[Required]
public double Sum { get; private set; }
[Required]
[DataMember]
[Required]
public OrderStatus Status { get; private set; } = OrderStatus.Undefined;
[Required]
[DataMember]
[Required]
public DateTime DateCreate { get; private set; } = DateTime.Now;
public DateTime? DateImplement { get; private set; }
[DataMember]
public DateTime? DateImplement { get; private set; }
public static Order? Create(OrderBindingModel Model)
{
@@ -44,6 +59,7 @@ namespace AutoWorkshopDatabaseImplement.Models
Id = Model.Id,
RepairId = Model.RepairId,
ClientId = Model.ClientId,
ImplementerId = Model.ImplementerId,
Count = Model.Count,
Sum = Model.Sum,
Status = Model.Status,
@@ -57,6 +73,7 @@ namespace AutoWorkshopDatabaseImplement.Models
if (Model is null)
return;
ImplementerId = Model.ImplementerId;
Status = Model.Status;
DateImplement = Model.DateImplement;
}
@@ -66,8 +83,11 @@ namespace AutoWorkshopDatabaseImplement.Models
Id = Id,
RepairId = RepairId,
ClientId = ClientId,
ImplementerId = ImplementerId,
RepairName = Repair.RepairName,
ClientFIO = Client.ClientFIO,
ClientEmail = Client.Email,
ImplementerFIO = Implementer?.ImplementerFIO,
Count = Count,
Sum = Sum,
Status = Status,

View File

@@ -3,22 +3,28 @@ using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;
namespace AutoWorkshopDatabaseImplement.Models
{
[DataContract]
public class Repair : IRepairModel
{
[DataMember]
public int Id { get; set; }
[Required]
[DataMember]
[Required]
public string RepairName { get; set; } = string.Empty;
[Required]
[DataMember]
[Required]
public double Price { get; set; }
private Dictionary<int, (IComponentModel, int)>? _repairComponents = null;
[NotMapped]
[DataMember]
[NotMapped]
public Dictionary<int, (IComponentModel, int)> RepairComponents
{
get

View File

@@ -11,4 +11,8 @@
<ProjectReference Include="..\AutoWorkshopDataModels\AutoWorkshopDataModels.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy /Y &quot;$(TargetDir)*.dll&quot; &quot;$(SolutionDir)ImplementationExtensions\*.dll&quot;" />
</Target>
</Project>

View File

@@ -11,8 +11,10 @@ namespace AutoWorkshopFileImplement
private readonly string OrderFileName = "Order.xml";
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; }
@@ -20,13 +22,19 @@ namespace AutoWorkshopFileImplement
public List<Client> Clients { get; private set; }
private DataFileSingleton()
public List<Implementer> Implementers { get; private set; }
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()
{
@@ -42,8 +50,10 @@ namespace AutoWorkshopFileImplement
public void SaveRepairs() => SaveData(Repairs, RepairFileName, "Repairs", 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 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,22 @@
using AutoWorkshopContracts.DI;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopFileImplement.Implements;
namespace AutoWorkshopFileImplement
{
public class ImplementationExtension : IImplementationExtension
{
public int Priority => 1;
public void RegisterServices()
{
DependencyManager.Instance.RegisterType<IClientStorage, ClientStorage>();
DependencyManager.Instance.RegisterType<IComponentStorage, ComponentStorage>();
DependencyManager.Instance.RegisterType<IImplementerStorage, ImplementerStorage>();
DependencyManager.Instance.RegisterType<IMessageInfoStorage, MessageInfoStorage>();
DependencyManager.Instance.RegisterType<IOrderStorage, OrderStorage>();
DependencyManager.Instance.RegisterType<IRepairStorage, RepairStorage>();
DependencyManager.Instance.RegisterType<IBackUpInfo, BackUpInfo>();
}
}
}

View File

@@ -0,0 +1,42 @@
using AutoWorkshopContracts.StoragesContracts;
using System.Reflection;
namespace AutoWorkshopFileImplement.Implements
{
public class BackUpInfo : IBackUpInfo
{
private readonly DataFileSingleton _source;
private readonly PropertyInfo[] _sourceProperties;
public BackUpInfo()
{
_source = DataFileSingleton.GetInstance();
_sourceProperties = _source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
}
public List<T>? GetList<T>() where T : class, new()
{
var RequiredType = typeof(T);
return (List<T>?)_sourceProperties
.FirstOrDefault(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericArguments()[0] == RequiredType)
?.GetValue(_source);
}
public Type? GetTypeByModelInterface(string ModelInterfaceName)
{
var Assembly = typeof(BackUpInfo).Assembly;
var Types = Assembly.GetTypes();
foreach (var Type in Types)
{
if (Type.IsClass && Type.GetInterface(ModelInterfaceName) != null)
{
return Type;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,97 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopFileImplement.Models;
namespace AutoWorkshopFileImplement.Implements
{
public class ImplementerStorage : IImplementerStorage
{
private readonly DataFileSingleton _source;
public ImplementerStorage()
{
_source = DataFileSingleton.GetInstance();
}
public List<ImplementerViewModel> GetFullList()
{
return _source.Implementers.Select(x => x.GetViewModel).ToList();
}
public List<ImplementerViewModel> GetFilteredList(ImplementerSearchModel Model)
{
if (Model == null)
return new();
if (Model.Id.HasValue)
{
var Res = GetElement(Model);
return Res != null ? new() { Res } : new();
}
if (Model.ImplementerFIO != null)
{
return _source.Implementers
.Where(x => x.ImplementerFIO.Equals(Model.ImplementerFIO))
.Select(x => x.GetViewModel)
.ToList();
}
return new();
}
public ImplementerViewModel? GetElement(ImplementerSearchModel Model)
{
if (Model.Id.HasValue)
return _source.Implementers.FirstOrDefault(x => x.Id == Model.Id)?.GetViewModel;
if (Model.ImplementerFIO != null && Model.Password != null)
return _source.Implementers.FirstOrDefault(x => x.ImplementerFIO.Equals(Model.ImplementerFIO) && x.Password.Equals(Model.Password))?.GetViewModel;
if (Model.ImplementerFIO != null)
return _source.Implementers.FirstOrDefault(x => x.ImplementerFIO.Equals(Model.ImplementerFIO))?.GetViewModel;
return null;
}
public ImplementerViewModel? Insert(ImplementerBindingModel Model)
{
Model.Id = _source.Implementers.Count > 0 ? _source.Implementers.Max(x => x.Id) + 1 : 1;
var Res = Implementer.Create(Model);
if (Res != null)
{
_source.Implementers.Add(Res);
_source.SaveImplementers();
}
return Res?.GetViewModel;
}
public ImplementerViewModel? Update(ImplementerBindingModel Model)
{
var Res = _source.Implementers.FirstOrDefault(x => x.Id == Model.Id);
if (Res != null)
{
Res.Update(Model);
_source.SaveImplementers();
}
return Res?.GetViewModel;
}
public ImplementerViewModel? Delete(ImplementerBindingModel Model)
{
var Res = _source.Implementers.FirstOrDefault(x => x.Id == Model.Id);
if (Res != null)
{
_source.Implementers.Remove(Res);
_source.SaveImplementers();
}
return Res?.GetViewModel;
}
}
}

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

@@ -26,14 +26,16 @@ namespace AutoWorkshopFileImplement.Implements
if (Model.DateFrom.HasValue)
{
return _source.Orders
.Where(x => (x.DateCreate >= Model.DateFrom && x.DateCreate <= Model.DateTo) && (!Model.ClientId.HasValue || x.ClientId == Model.ClientId))
.Select(x => AddClientFIO(AddRepairName(x.GetViewModel)))
.Where(x => (x.DateCreate >= Model.DateFrom && x.DateCreate <= Model.DateTo) && (!Model.ClientId.HasValue || x.ClientId == Model.ClientId)
&& (!Model.ImplementerId.HasValue || x.ImplementerId == Model.ImplementerId))
.Select(x => AddImplementerFIO(AddClientFIO(AddRepairName(x.GetViewModel))))
.ToList();
}
return _source.Orders
.Where(x => (Model.Id.HasValue && x.Id == Model.Id) || (Model.ClientId.HasValue && x.ClientId == Model.ClientId))
.Select(x => AddClientFIO(AddRepairName(x.GetViewModel)))
.Where(x => (Model.Id.HasValue && x.Id == Model.Id) || (Model.ClientId.HasValue && x.ClientId == Model.ClientId)
|| (Model.ImplementerId.HasValue && x.ImplementerId == Model.ImplementerId))
.Select(x => AddImplementerFIO(AddClientFIO(AddRepairName(x.GetViewModel))))
.ToList();
}
@@ -54,15 +56,17 @@ namespace AutoWorkshopFileImplement.Implements
public OrderViewModel? GetElement(OrderSearchModel Model)
{
if (!Model.Id.HasValue)
if (!Model.Id.HasValue && !Model.ImplementerId.HasValue && !Model.Status.HasValue)
return null;
var Order = _source.Orders.FirstOrDefault(x => (Model.Id.HasValue && x.Id == Model.Id));
var Order = _source.Orders.FirstOrDefault(x =>
(Model.Id.HasValue && x.Id == Model.Id)
|| (Model.ImplementerId.HasValue && Model.Status.HasValue && x.ImplementerId == Model.ImplementerId && x.Status == Model.Status) );
if (Order == null)
return null;
return AddRepairName(Order.GetViewModel);
return AddImplementerFIO(AddClientFIO(AddRepairName(Order.GetViewModel)));
}
public OrderViewModel? Insert(OrderBindingModel Model)
@@ -108,5 +112,16 @@ namespace AutoWorkshopFileImplement.Implements
Model.ClientFIO = SelectedClient?.ClientFIO ?? string.Empty;
return Model;
}
public OrderViewModel AddImplementerFIO(OrderViewModel Model)
{
var SelectedImplementer = _source.Implementers.FirstOrDefault(x => x.Id == Model.ImplementerId);
if (SelectedImplementer != null)
{
Model.ImplementerFIO = SelectedImplementer.ImplementerFIO;
}
return Model;
}
}
}

View File

@@ -1,19 +1,25 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.Runtime.Serialization;
using System.Xml.Linq;
namespace AutoWorkshopFileImplement.Models
{
public class Client : IClientModel
[DataContract]
public class Client : IClientModel
{
[DataMember]
public int Id { get; private set; }
public string ClientFIO { get; private set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
[DataMember]
public string ClientFIO { get; private set; } = string.Empty;
[DataMember]
public string Email { get; set; } = string.Empty;
[DataMember]
public string Password { get; set; } = string.Empty;
public static Client? Create(ClientBindingModel Model)
{

View File

@@ -1,17 +1,22 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.Runtime.Serialization;
using System.Xml.Linq;
namespace AutoWorkshopFileImplement.Models
{
public class Component : IComponentModel
[DataContract]
public class Component : IComponentModel
{
[DataMember]
public int Id { get; private set; }
public string ComponentName { get; private set; } = string.Empty;
public double Cost { get; set; }
[DataMember]
public string ComponentName { get; private set; } = string.Empty;
[DataMember]
public double Cost { get; set; }
public static Component? Create(ComponentBindingModel Model)
{

View File

@@ -0,0 +1,86 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.Runtime.Serialization;
using System.Xml.Linq;
namespace AutoWorkshopFileImplement.Models
{
[DataContract]
public class Implementer : IImplementerModel
{
[DataMember]
public int Id { get; private set; }
[DataMember]
public string ImplementerFIO { get; private set; } = string.Empty;
[DataMember]
public string Password { get; private set; } = string.Empty;
[DataMember]
public int WorkExperience { get; private set; }
[DataMember]
public int Qualification { get; private set; }
public static Implementer? Create(ImplementerBindingModel Model)
{
if (Model == null)
return null;
return new()
{
Id = Model.Id,
ImplementerFIO = Model.ImplementerFIO,
Password = Model.Password,
WorkExperience = Model.WorkExperience,
Qualification = Model.Qualification,
};
}
public static Implementer? Create(XElement Element)
{
if (Element == null)
return null;
return new()
{
Id = Convert.ToInt32(Element.Attribute("Id")!.Value),
ImplementerFIO = Element.Element("ImplementerFIO")!.Value,
Password = Element.Element("Password")!.Value,
WorkExperience = Convert.ToInt32(Element.Element("WorkExperience")!.Value),
Qualification = Convert.ToInt32(Element.Element("Qualification")!.Value),
};
}
public void Update(ImplementerBindingModel Model)
{
if (Model == null)
return;
ImplementerFIO = Model.ImplementerFIO;
Password = Model.Password;
WorkExperience = Model.WorkExperience;
Qualification = Model.Qualification;
}
public ImplementerViewModel GetViewModel => new()
{
Id = Id,
ImplementerFIO = ImplementerFIO,
Password = Password,
WorkExperience = WorkExperience,
Qualification = Qualification,
};
public XElement GetXElement => new(
"Implementer",
new XAttribute("Id", Id),
new XElement("ImplementerFIO", ImplementerFIO),
new XElement("Password", Password),
new XElement("WorkExperience", WorkExperience),
new XElement("Qualification", Qualification)
);
}
}

View File

@@ -0,0 +1,85 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.Runtime.Serialization;
using System.Xml.Linq;
namespace AutoWorkshopFileImplement.Models
{
[DataContract]
public class MessageInfo : IMessageInfoModel
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string MessageId { get; set; } = string.Empty;
[DataMember]
public int? ClientId { get; set; }
[DataMember]
public string SenderName { get; set; } = string.Empty;
[DataMember]
public DateTime DateDelivery { get; set; }
[DataMember]
public string Subject { get; set; } = string.Empty;
[DataMember]
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

@@ -2,27 +2,40 @@
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Enums;
using AutoWorkshopDataModels.Models;
using System.Runtime.Serialization;
using System.Xml.Linq;
namespace AutoWorkshopFileImplement.Models
{
public class Order : IOrderModel
[DataContract]
public class Order : IOrderModel
{
[DataMember]
public int Id { get; private set; }
public int RepairId { get; private set; }
[DataMember]
public int RepairId { get; private set; }
public int ClientId { get; private set; }
[DataMember]
public int ClientId { get; private set; }
public int Count { get; private set; }
[DataMember]
public int? ImplementerId { get; set; }
public double Sum { get; private set; }
[DataMember]
public int Count { get; private set; }
public OrderStatus Status { get; private set; }
[DataMember]
public double Sum { get; private set; }
public DateTime DateCreate { get; private set; }
[DataMember]
public OrderStatus Status { get; private set; }
public DateTime? DateImplement { get; private set; }
[DataMember]
public DateTime DateCreate { get; private set; }
[DataMember]
public DateTime? DateImplement { get; private set; }
public static Order? Create(OrderBindingModel? Model)
{
@@ -34,6 +47,7 @@ namespace AutoWorkshopFileImplement.Models
Id = Model.Id,
RepairId = Model.RepairId,
ClientId = Model.ClientId,
ImplementerId = Model.ImplementerId,
Count = Model.Count,
Sum = Model.Sum,
Status = Model.Status,
@@ -52,6 +66,7 @@ namespace AutoWorkshopFileImplement.Models
Id = Convert.ToInt32(Element.Attribute("Id")!.Value),
RepairId = Convert.ToInt32(Element.Element("RepairId")!.Value),
ClientId = Convert.ToInt32(Element.Element("ClientId")!.Value),
ImplementerId = Convert.ToInt32(Element.Element("ImplementerId")!.Value),
Count = Convert.ToInt32(Element.Element("Count")!.Value),
Sum = Convert.ToDouble(Element.Element("Sum")!.Value),
Status = (OrderStatus)Enum.Parse(typeof(OrderStatus), Element.Element("Status")!.Value),
@@ -65,6 +80,7 @@ namespace AutoWorkshopFileImplement.Models
if (Model is null)
return;
ImplementerId = Model.ImplementerId;
Status = Model.Status;
DateImplement = Model.DateImplement;
}
@@ -74,6 +90,7 @@ namespace AutoWorkshopFileImplement.Models
Id = Id,
RepairId = RepairId,
ClientId = ClientId,
ImplementerId = ImplementerId,
Count = Count,
Sum = Sum,
Status = Status,
@@ -86,6 +103,7 @@ namespace AutoWorkshopFileImplement.Models
new XAttribute("Id", Id),
new XElement("RepairId", RepairId),
new XElement("ClientId", ClientId),
new XElement("ImplementerId", ImplementerId),
new XElement("Count", Count.ToString()),
new XElement("Sum", Sum.ToString()),
new XElement("Status", Status.ToString()),

View File

@@ -1,23 +1,29 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.Runtime.Serialization;
using System.Xml.Linq;
namespace AutoWorkshopFileImplement.Models
{
public class Repair : IRepairModel
[DataContract]
public class Repair : IRepairModel
{
public int Id { get; private set; }
public string RepairName { get; private set; } = string.Empty;
public double Price { get; private set; }
[DataMember]
public int Id { get; private set; }
[DataMember]
public string RepairName { get; private set; } = string.Empty;
[DataMember]
public double Price { get; private set; }
public Dictionary<int, int> Components { get; private set; } = new();
private Dictionary<int, (IComponentModel, int)>? _RepairComponents = null;
public Dictionary<int, (IComponentModel, int)> RepairComponents
[DataMember]
public Dictionary<int, (IComponentModel, int)> RepairComponents
{
get
{

View File

@@ -11,4 +11,8 @@
<ProjectReference Include="..\AutoWorkshopDataModels\AutoWorkshopDataModels.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy /Y &quot;$(TargetDir)*.dll&quot; &quot;$(SolutionDir)ImplementationExtensions\*.dll&quot;" />
</Target>
</Project>

View File

@@ -14,12 +14,18 @@ namespace AutoWorkshopListImplement
public List<Client> Clients { get; set; }
public List<Implementer> Implementers { get; set; }
public List<MessageInfo> Messages { get; set; }
private DataListSingleton()
{
Components = new List<Component>();
Orders = new List<Order>();
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,22 @@
using AutoWorkshopContracts.DI;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopListImplement.Implements;
namespace AutoWorkshopListImplement
{
public class ImplementationExtension : IImplementationExtension
{
public int Priority => 0;
public void RegisterServices()
{
DependencyManager.Instance.RegisterType<IClientStorage, ClientStorage>();
DependencyManager.Instance.RegisterType<IComponentStorage, ComponentStorage>();
DependencyManager.Instance.RegisterType<IImplementerStorage, ImplementerStorage>();
DependencyManager.Instance.RegisterType<IMessageInfoStorage, MessageInfoStorage>();
DependencyManager.Instance.RegisterType<IOrderStorage, OrderStorage>();
DependencyManager.Instance.RegisterType<IRepairStorage, RepairStorage>();
DependencyManager.Instance.RegisterType<IBackUpInfo, BackUpInfo>();
}
}
}

View File

@@ -0,0 +1,17 @@
using AutoWorkshopContracts.StoragesContracts;
namespace AutoWorkshopListImplement.Implements
{
public class BackUpInfo : IBackUpInfo
{
public List<T>? GetList<T>() where T : class, new()
{
throw new NotImplementedException();
}
public Type? GetTypeByModelInterface(string ModelInterfaceName)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,104 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopListImplement.Models;
namespace AutoWorkshopListImplement.Implements
{
public class ImplementerStorage : IImplementerStorage
{
private readonly DataListSingleton _source;
public ImplementerStorage()
{
_source = DataListSingleton.GetInstance();
}
public List<ImplementerViewModel> GetFullList()
{
var Result = new List<ImplementerViewModel>();
foreach (var Implementer in _source.Implementers)
{
Result.Add(Implementer.GetViewModel);
}
return Result;
}
public List<ImplementerViewModel> GetFilteredList(ImplementerSearchModel Model)
{
if (string.IsNullOrEmpty(Model.ImplementerFIO))
return new();
return _source.Implementers
.Where(x => (!string.IsNullOrEmpty(Model.ImplementerFIO) && x.ImplementerFIO.Contains(Model.ImplementerFIO)))
.Select(x => x.GetViewModel)
.ToList();
}
public ImplementerViewModel? GetElement(ImplementerSearchModel Model)
{
foreach (var Implementer in _source.Implementers)
{
if ((Model.Id.HasValue && Implementer.Id == Model.Id) ||
(!string.IsNullOrEmpty(Model.ImplementerFIO) && Implementer.ImplementerFIO == Model.ImplementerFIO))
{
return Implementer.GetViewModel;
}
}
return null;
}
public ImplementerViewModel? Insert(ImplementerBindingModel Model)
{
Model.Id = 1;
foreach (var Implementer in _source.Implementers)
{
if (Model.Id <= Implementer.Id)
{
Model.Id = Implementer.Id + 1;
}
}
var NewImplementer = Implementer.Create(Model);
if (NewImplementer == null)
return null;
_source.Implementers.Add(NewImplementer);
return NewImplementer.GetViewModel;
}
public ImplementerViewModel? Update(ImplementerBindingModel Model)
{
foreach (var Implementer in _source.Implementers)
{
if (Implementer.Id == Model.Id)
{
Implementer.Update(Model);
return Implementer.GetViewModel;
}
}
return null;
}
public ImplementerViewModel? Delete(ImplementerBindingModel Model)
{
for (int i = 0; i < _source.Implementers.Count; ++i)
{
if (_source.Implementers[i].Id == Model.Id)
{
var Implementer = _source.Implementers[i];
_source.Implementers.RemoveAt(i);
return Implementer.GetViewModel;
}
}
return null;
}
}
}

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

@@ -32,27 +32,30 @@ namespace AutoWorkshopListImplement.Implements
if (Model.DateFrom.HasValue)
{
return _source.Orders
.Where(x => (x.DateCreate >= Model.DateFrom && x.DateCreate <= Model.DateTo) && (!Model.ClientId.HasValue || x.ClientId == Model.ClientId))
.Select(x => JoinClientFIO(JoinRepairName(x.GetViewModel)))
.Where(x => (x.DateCreate >= Model.DateFrom && x.DateCreate <= Model.DateTo) && (!Model.ClientId.HasValue || x.ClientId == Model.ClientId)
&& (!Model.ImplementerId.HasValue || x.ImplementerId == Model.ImplementerId))
.Select(x => JoinImplementerFIO(JoinClientFIO(JoinRepairName(x.GetViewModel))))
.ToList();
}
return _source.Orders
.Where(x => (Model.Id.HasValue && x.Id == Model.Id) || (Model.ClientId.HasValue && x.ClientId == Model.ClientId))
.Select(x => JoinClientFIO(JoinRepairName(x.GetViewModel)))
.Where(x => (Model.Id.HasValue && x.Id == Model.Id) || (Model.ClientId.HasValue && x.ClientId == Model.ClientId)
|| (Model.ImplementerId.HasValue && x.ImplementerId == Model.ImplementerId))
.Select(x => JoinImplementerFIO(JoinClientFIO(JoinRepairName(x.GetViewModel))))
.ToList();
}
public OrderViewModel? GetElement(OrderSearchModel Model)
{
if (!Model.Id.HasValue)
if (!Model.Id.HasValue && !Model.ImplementerId.HasValue && !Model.Status.HasValue)
return null;
foreach (var Order in _source.Orders)
{
if (Order.Id == Model.Id)
if ((Model.Id.HasValue && Order.Id == Model.Id)
|| (Model.ImplementerId.HasValue && Model.Status.HasValue && Order.ImplementerId == Model.ImplementerId && Order.Status == Model.Status))
{
return JoinRepairName(Order.GetViewModel);
return JoinImplementerFIO(JoinClientFIO(JoinRepairName(Order.GetViewModel)));
}
}
@@ -130,5 +133,16 @@ namespace AutoWorkshopListImplement.Implements
}
return Model;
}
public OrderViewModel JoinImplementerFIO(OrderViewModel Model)
{
var SelectedImplementer = _source.Implementers.FirstOrDefault(x => x.Id == Model.ImplementerId);
if (SelectedImplementer != null)
{
Model.ImplementerFIO = SelectedImplementer.ImplementerFIO;
}
return Model;
}
}
}

View File

@@ -0,0 +1,54 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopListImplement.Models
{
public class Implementer : IImplementerModel
{
public int Id { get; private set; }
public string ImplementerFIO { get; private set; } = string.Empty;
public string Password { get; private set; } = string.Empty;
public int WorkExperience { get; private set; }
public int Qualification { get; private set; }
public static Implementer? Create(ImplementerBindingModel Model)
{
if (Model == null)
{
return null;
}
return new()
{
Id = Model.Id,
Password = Model.Password,
Qualification = Model.Qualification,
ImplementerFIO = Model.ImplementerFIO,
WorkExperience = Model.WorkExperience,
};
}
public void Update(ImplementerBindingModel Model)
{
if (Model == null)
return;
Password = Model.Password;
Qualification = Model.Qualification;
ImplementerFIO = Model.ImplementerFIO;
WorkExperience = Model.WorkExperience;
}
public ImplementerViewModel GetViewModel => new()
{
Id = Id,
Password = Password,
Qualification = Qualification,
ImplementerFIO = ImplementerFIO,
};
}
}

View File

@@ -0,0 +1,49 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopListImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
public int Id { get; set; }
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

@@ -13,6 +13,8 @@ namespace AutoWorkshopListImplement.Models
public int ClientId { get; private set; }
public int? ImplementerId { get; private set; }
public int Count { get; private set; }
public double Sum { get; private set; }
@@ -33,6 +35,7 @@ namespace AutoWorkshopListImplement.Models
Id = Model.Id,
RepairId = Model.RepairId,
ClientId = Model.ClientId,
ImplementerId = Model.ImplementerId,
Count = Model.Count,
Sum = Model.Sum,
Status = Model.Status,
@@ -46,11 +49,7 @@ namespace AutoWorkshopListImplement.Models
if (Model == null)
return;
RepairId = Model.RepairId;
Count = Model.Count;
Sum = Model.Sum;
Status = Model.Status;
DateCreate = Model.DateCreate;
DateImplement = Model.DateImplement;
}
@@ -59,6 +58,7 @@ namespace AutoWorkshopListImplement.Models
Id = Id,
RepairId = RepairId,
ClientId = ClientId,
ImplementerId = ImplementerId,
Count = Count,
Sum = Sum,
Status = Status,

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

@@ -0,0 +1,108 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.BusinessLogicsContracts;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Enums;
using Microsoft.AspNetCore.Mvc;
namespace AutoWorkshopRestApi.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class ImplementerController : Controller
{
private readonly ILogger _logger;
private readonly IOrderLogic _order;
private readonly IImplementerLogic _logic;
public ImplementerController(IOrderLogic Order, IImplementerLogic Logic, ILogger<ImplementerController> Logger)
{
_logger = Logger;
_order = Order;
_logic = Logic;
}
[HttpGet]
public ImplementerViewModel? Login(string login, string password)
{
try
{
return _logic.ReadElement(new ImplementerSearchModel
{
ImplementerFIO = login,
Password = password
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка авторизации сотрудника");
throw;
}
}
[HttpGet]
public List<OrderViewModel>? GetNewOrders()
{
try
{
return _order.ReadList(new OrderSearchModel
{
Status = OrderStatus.Accepted
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения новых заказов");
throw;
}
}
[HttpGet]
public OrderViewModel? GetImplementerOrder(int implementerId)
{
try
{
return _order.ReadElement(new OrderSearchModel
{
ImplementerId = implementerId
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения текущего заказа исполнителя");
throw;
}
}
[HttpPost]
public void TakeOrderInWork(OrderBindingModel Model)
{
try
{
_order.TakeOrderInWork(Model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка перевода заказа с №{Id} в работу", Model.Id);
throw;
}
}
[HttpPost]
public void FinishOrder(OrderBindingModel Model)
{
try
{
_order.FinishOrder(Model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка отметки о готовности заказа с №{Id}", Model.Id);
throw;
}
}
}
}

View File

@@ -1,5 +1,8 @@
using AutoWorkshopBusinessLogic.BusinessLogics;
using AutoWorkshopBusinessLogic.MailWorker;
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.BusinessLogicsContracts;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopDatabaseImplement.Implements;
using Microsoft.OpenApi.Models;
@@ -12,9 +15,17 @@ Builder.Logging.AddLog4Net("log4net.config");
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();
Builder.Services.AddEndpointsApiExplorer();
@@ -29,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": "kxdk seny yjaj vrav"
}

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="kxdk seny yjaj vrav" />
</appSettings>
</configuration>

View File

@@ -28,4 +28,10 @@
</None>
</ItemGroup>
<ItemGroup>
<None Update="nlog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,44 @@
using AutoWorkshopContracts.Attrubites;
namespace AutoWorkshopView
{
public static class DataGridViewExtension
{
public static void FillAndConfigGrid<T>(this DataGridView Grid, List<T>? Data)
{
if (Data == null)
return;
Grid.DataSource = Data;
var Type = typeof(T);
var Properties = Type.GetProperties();
foreach (DataGridViewColumn Column in Grid.Columns)
{
var Property = Properties.FirstOrDefault(x => x.Name == Column.Name);
if (Property == null)
throw new InvalidOperationException($"В типе {Type.Name} не найдено свойство с именем {Column.Name}");
var Attribute = Property.GetCustomAttributes(typeof(ColumnAttribute), true)?.SingleOrDefault();
if (Attribute == null)
throw new InvalidOperationException($"Не найден атрибут типа ColumnAttribute для свойства {Property.Name}");
if (Attribute is ColumnAttribute СolumnAttr)
{
Column.HeaderText = СolumnAttr.Title;
Column.Visible = СolumnAttr.Visible;
if (СolumnAttr.IsUseAutoSize)
{
Column.AutoSizeMode = (DataGridViewAutoSizeColumnMode)Enum.Parse(typeof(DataGridViewAutoSizeColumnMode), СolumnAttr.GridViewAutoSize.ToString());
}
else
{
Column.Width = СolumnAttr.Width;
}
}
}
}
}
}

View File

@@ -21,17 +21,7 @@ namespace AutoWorkshopView.Forms
{
try
{
var List = _clientLogic.ReadList(null);
if (List != null)
{
DataGridView.DataSource = List;
DataGridView.Columns["Id"].Visible = false;
DataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
DataGridView.Columns["Email"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
DataGridView.Columns["Password"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
DataGridView.FillAndConfigGrid(_clientLogic.ReadList(null));
_logger.LogInformation("Загрузка клиентов");
}
catch (Exception ex)

View File

@@ -1,5 +1,6 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.DI;
using Microsoft.Extensions.Logging;
namespace AutoWorkshopView.Forms
@@ -25,15 +26,7 @@ namespace AutoWorkshopView.Forms
{
try
{
var List = _logic.ReadList(null);
if (List != null)
{
DataGridView.DataSource = List;
DataGridView.Columns["Id"].Visible = false;
DataGridView.Columns["ComponentName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
DataGridView.FillAndConfigGrid(_logic.ReadList(null));
_logger.LogInformation("Загрузка компонентов");
}
catch (Exception ex)
@@ -45,9 +38,9 @@ namespace AutoWorkshopView.Forms
private void AddButton_Click(object sender, EventArgs e)
{
var Service = Program.ServiceProvider?.GetService(typeof(FormComponent));
if (Service is FormComponent Form)
var Service = DependencyManager.Instance.Resolve<FormComponent>();
if (Service is FormComponent Form)
{
if (Form.ShowDialog() == DialogResult.OK)
{
@@ -60,8 +53,8 @@ namespace AutoWorkshopView.Forms
{
if (DataGridView.SelectedRows.Count == 1)
{
var Service = Program.ServiceProvider?.GetService(typeof(FormComponent));
if (Service is FormComponent Form)
var Service = DependencyManager.Instance.Resolve<FormComponent>();
if (Service is FormComponent Form)
{
Form.Id = Convert.ToInt32(DataGridView.SelectedRows[0].Cells["Id"].Value);
if (Form.ShowDialog() == DialogResult.OK)

View File

@@ -28,6 +28,8 @@
/// </summary>
private void InitializeComponent()
{
ClientLabel = new Label();
ClientComboBox = new ComboBox();
RepairComboBox = new ComboBox();
CountTextBox = new TextBox();
SumTextBox = new TextBox();
@@ -38,6 +40,24 @@
SumLabel = new Label();
SuspendLayout();
//
// ClientLabel
//
ClientLabel.AutoSize = true;
ClientLabel.Location = new Point(12, 102);
ClientLabel.Name = "ClientLabel";
ClientLabel.Size = new Size(49, 15);
ClientLabel.TabIndex = 8;
ClientLabel.Text = "Клиент:";
//
// ClientComboBox
//
ClientComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
ClientComboBox.FormattingEnabled = true;
ClientComboBox.Location = new Point(103, 99);
ClientComboBox.Name = "ClientComboBox";
ClientComboBox.Size = new Size(232, 23);
ClientComboBox.TabIndex = 9;
//
// RepairComboBox
//
RepairComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
@@ -66,7 +86,7 @@
//
// SaveButton
//
SaveButton.Location = new Point(173, 107);
SaveButton.Location = new Point(173, 139);
SaveButton.Name = "SaveButton";
SaveButton.Size = new Size(81, 23);
SaveButton.TabIndex = 3;
@@ -76,7 +96,7 @@
//
// CancelButton
//
CancelButton.Location = new Point(260, 107);
CancelButton.Location = new Point(260, 139);
CancelButton.Name = "CancelButton";
CancelButton.Size = new Size(75, 23);
CancelButton.TabIndex = 4;
@@ -110,33 +130,15 @@
SumLabel.Size = new Size(48, 15);
SumLabel.TabIndex = 7;
SumLabel.Text = "Сумма:";
//
// labelClient
//
labelClient.AutoSize = true;
labelClient.Location = new Point(26, 131);
labelClient.Name = "labelClient";
labelClient.Size = new Size(58, 20);
labelClient.TabIndex = 8;
labelClient.Text = "Клиент";
//
// comboBoxClient
//
comboBoxClient.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoxClient.FormattingEnabled = true;
comboBoxClient.Location = new Point(131, 131);
comboBoxClient.Name = "comboBoxClient";
comboBoxClient.Size = new Size(260, 28);
comboBoxClient.TabIndex = 9;
//
// FormCreateOrder
//
AutoScaleDimensions = new SizeF(7F, 15F);
//
// FormCreateOrder
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(348, 142);
Controls.Add(comboBoxClient);
Controls.Add(labelClient);
Controls.Add(SumLabel);
ClientSize = new Size(348, 183);
Controls.Add(ClientComboBox);
Controls.Add(ClientLabel);
Controls.Add(SumLabel);
Controls.Add(CountLabel);
Controls.Add(RepairLabel);
Controls.Add(CancelButton);
@@ -161,7 +163,7 @@
private Label RepairLabel;
private Label CountLabel;
private Label SumLabel;
private Label labelClient;
private ComboBox comboBoxClient;
private Label ClientLabel;
private ComboBox ClientComboBox;
}
}

View File

@@ -51,10 +51,10 @@ namespace AutoWorkshopView.Forms
var list = _clientLogic.ReadList(null);
if (list != null)
{
comboBoxClient.DisplayMember = "ClientFIO";
comboBoxClient.ValueMember = "Id";
comboBoxClient.DataSource = list;
comboBoxClient.SelectedItem = null;
ClientComboBox.DisplayMember = "ClientFIO";
ClientComboBox.ValueMember = "Id";
ClientComboBox.DataSource = list;
ClientComboBox.SelectedItem = null;
}
_logger.LogInformation("Клиенты загружены");
}
@@ -110,6 +110,12 @@ namespace AutoWorkshopView.Forms
return;
}
if (ClientComboBox.SelectedValue == null)
{
MessageBox.Show("Выберите клиента", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Создание заказа");
try
@@ -117,6 +123,7 @@ namespace AutoWorkshopView.Forms
var OperationResult = _orderLogic.CreateOrder(new OrderBindingModel
{
RepairId = Convert.ToInt32(RepairComboBox.SelectedValue),
ClientId = Convert.ToInt32(ClientComboBox.SelectedValue),
Count = Convert.ToInt32(CountTextBox.Text),
Sum = Convert.ToDouble(SumTextBox.Text)
});

View File

@@ -0,0 +1,173 @@
namespace AutoWorkshopView.Forms
{
partial class FormImplementer
{
/// <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()
{
FioTextBox = new TextBox();
FioLabel = new Label();
PasswordTextBox = new TextBox();
PasswordLabel = new Label();
WorkExperienceLabel = new Label();
WorkExperienceNumericUpDown = new NumericUpDown();
QualificationNumericUpDown = new NumericUpDown();
QualificationLabel = new Label();
CancelButton = new Button();
SaveButton = new Button();
((System.ComponentModel.ISupportInitialize)WorkExperienceNumericUpDown).BeginInit();
((System.ComponentModel.ISupportInitialize)QualificationNumericUpDown).BeginInit();
SuspendLayout();
//
// FioTextBox
//
FioTextBox.Location = new Point(137, 9);
FioTextBox.Margin = new Padding(3, 2, 3, 2);
FioTextBox.Name = "FioTextBox";
FioTextBox.Size = new Size(335, 23);
FioTextBox.TabIndex = 3;
//
// FioLabel
//
FioLabel.AutoSize = true;
FioLabel.Location = new Point(10, 12);
FioLabel.Name = "FioLabel";
FioLabel.Size = new Size(112, 15);
FioLabel.TabIndex = 2;
FioLabel.Text = "ФИО исполнителя:";
//
// PasswordTextBox
//
PasswordTextBox.Location = new Point(137, 40);
PasswordTextBox.Margin = new Padding(3, 2, 3, 2);
PasswordTextBox.Name = "PasswordTextBox";
PasswordTextBox.Size = new Size(335, 23);
PasswordTextBox.TabIndex = 5;
//
// PasswordLabel
//
PasswordLabel.AutoSize = true;
PasswordLabel.Location = new Point(10, 43);
PasswordLabel.Name = "PasswordLabel";
PasswordLabel.Size = new Size(52, 15);
PasswordLabel.TabIndex = 4;
PasswordLabel.Text = "Пароль:";
//
// WorkExperienceLabel
//
WorkExperienceLabel.AutoSize = true;
WorkExperienceLabel.Location = new Point(10, 75);
WorkExperienceLabel.Name = "WorkExperienceLabel";
WorkExperienceLabel.Size = new Size(84, 15);
WorkExperienceLabel.TabIndex = 6;
WorkExperienceLabel.Text = "Опыт работы:";
//
// WorkExperienceNumericUpDown
//
WorkExperienceNumericUpDown.Location = new Point(137, 73);
WorkExperienceNumericUpDown.Margin = new Padding(3, 2, 3, 2);
WorkExperienceNumericUpDown.Name = "WorkExperienceNumericUpDown";
WorkExperienceNumericUpDown.Size = new Size(108, 23);
WorkExperienceNumericUpDown.TabIndex = 8;
//
// QualificationNumericUpDown
//
QualificationNumericUpDown.Location = new Point(137, 106);
QualificationNumericUpDown.Margin = new Padding(3, 2, 3, 2);
QualificationNumericUpDown.Name = "QualificationNumericUpDown";
QualificationNumericUpDown.Size = new Size(108, 23);
QualificationNumericUpDown.TabIndex = 10;
//
// QualificationLabel
//
QualificationLabel.AutoSize = true;
QualificationLabel.Location = new Point(10, 108);
QualificationLabel.Name = "QualificationLabel";
QualificationLabel.Size = new Size(91, 15);
QualificationLabel.TabIndex = 9;
QualificationLabel.Text = "Квалификация:";
//
// CancelButton
//
CancelButton.Location = new Point(353, 142);
CancelButton.Margin = new Padding(3, 2, 3, 2);
CancelButton.Name = "CancelButton";
CancelButton.Size = new Size(119, 30);
CancelButton.TabIndex = 12;
CancelButton.Text = "Отмена";
CancelButton.UseVisualStyleBackColor = true;
CancelButton.Click += CancelButton_Click;
//
// SaveButton
//
SaveButton.Location = new Point(233, 142);
SaveButton.Margin = new Padding(3, 2, 3, 2);
SaveButton.Name = "SaveButton";
SaveButton.Size = new Size(114, 30);
SaveButton.TabIndex = 11;
SaveButton.Text = "Сохранить";
SaveButton.UseVisualStyleBackColor = true;
SaveButton.Click += SaveButton_Click;
//
// FormImplementer
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(482, 183);
Controls.Add(CancelButton);
Controls.Add(SaveButton);
Controls.Add(QualificationNumericUpDown);
Controls.Add(QualificationLabel);
Controls.Add(WorkExperienceNumericUpDown);
Controls.Add(WorkExperienceLabel);
Controls.Add(PasswordTextBox);
Controls.Add(PasswordLabel);
Controls.Add(FioTextBox);
Controls.Add(FioLabel);
Margin = new Padding(3, 2, 3, 2);
Name = "FormImplementer";
Text = "Исполнитель";
Load += FormImplementer_Load;
((System.ComponentModel.ISupportInitialize)WorkExperienceNumericUpDown).EndInit();
((System.ComponentModel.ISupportInitialize)QualificationNumericUpDown).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox FioTextBox;
private Label FioLabel;
private TextBox PasswordTextBox;
private Label PasswordLabel;
private Label WorkExperienceLabel;
private NumericUpDown WorkExperienceNumericUpDown;
private NumericUpDown QualificationNumericUpDown;
private Label QualificationLabel;
private Button CancelButton;
private Button SaveButton;
}
}

Some files were not shown because too many files have changed in this diff Show More