работает

This commit is contained in:
Николай 2023-04-30 13:37:36 +04:00
parent 35c6c08bc4
commit cbeed33301
24 changed files with 1767 additions and 267 deletions

View File

@ -11,6 +11,7 @@ namespace FoodOrdersClientApp
private static readonly HttpClient _client = new();
public static ClientViewModel? Client { get; set; } = null;
public static int CurrentPage { get; set; } = 0;
public static void Connect(IConfiguration configuration)
{

View File

@ -3,6 +3,9 @@ using FoodOrdersContracts.BindingModels;
using FoodOrdersContracts.ViewModels;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Text;
using FoodOrdersContracts.SearchModels;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace FoodOrdersClientApp.Controllers
{
@ -151,7 +154,48 @@ namespace FoodOrdersClientApp.Controllers
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client.Id}"));
return View();
}
/// <summary>
/// Switches the page.
/// </summary>
/// <returns>Возвращает кортеж с таблицой в html, текущей страницей писем, выключать ли кнопку пред. страницы, выключать ли кнопку след. страницы</returns>
[HttpGet]
public Tuple<string?, string?, bool, bool>? SwitchPage(bool isNext)
{
if (isNext)
{
APIClient.CurrentPage++;
}
else
{
if (APIClient.CurrentPage == 1)
{
return null;
}
APIClient.CurrentPage--;
}
var res = APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client!.Id}&page={APIClient.CurrentPage}");
if (isNext && (res == null || res.Count == 0))
{
APIClient.CurrentPage--;
return Tuple.Create<string?, string?, bool, bool>(null, null, APIClient.CurrentPage != 1, false);
}
StringBuilder htmlTable = new();
foreach (var mail in res)
{
htmlTable.Append("<tr>" +
$"<td>{mail.DateDelivery}</td>" +
$"<td>{mail.Subject}</td>" +
$"<td>{mail.Body}</td>" +
"<td>" + (mail.HasRead ? "Прочитано" : "Непрочитано") + "</td>" +
$"<td>{mail.Reply}</td>" +
"</tr>");
}
return Tuple.Create<string?, string?, bool, bool>(htmlTable.ToString(), APIClient.CurrentPage.ToString(), APIClient.CurrentPage != 1, true);
}
}
}

View File

@ -1,54 +1,80 @@
@using FoodOrdersContracts.ViewModels
@model List<MessageInfoViewModel>
@{
ViewData["Title"] = "Mails";
@{
ViewData["Title"] = "Mails";
}
<div class="text-center">
<h1 class="display-4">Заказы</h1>
<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>
<th>
Статус
</th>
<th>
Ответ
</th>
</tr>
</thead>
<tbody id="mails-table-body">
</tbody>
</table>
<ul class="pagination justify-content-center">
<li id="prev-page" class="page-item">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
<span class="sr-only">Предыдущее</span>
</a>
</li>
<li class="page-item">
<a id="current-page" class="page-link"></a>
</li>
<li id="next-page" class="page-item">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
<span class="sr-only">Следующее</span>
</a>
</li>
</ul>
</div>
<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>
<script>
function onClicked(isNext) {
$.ajax({
method: "GET",
url: "/Home/SwitchPage",
data: { isNext: isNext },
success: function (result) {
if (result != null) {
if (result.item1 != null && result.item2 != null) {
$("#mails-table-body").html(result.item1);
$("#current-page").text(result.item2);
}
if (result.item3)
$("#prev-page").removeClass("page-item disabled");
else
$("#prev-page").addClass("page-item disabled");
if (result.item4)
$("#next-page").removeClass("page-item disabled");
else
$("#next-page").addClass("page-item disabled");
}
}
});
}
// Чтобы в первый раз загрузить данные и попасть на первую страницу
onClicked(true);
$("#prev-page").on('click', () => onClicked(false));
$("#next-page").on('click', () => onClicked(true));
</script>

View File

@ -7,6 +7,9 @@
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/FoodOrdersClientApp.styles.css" asp-append-version="true" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</head>
<body>
<header>

View File

@ -2,63 +2,105 @@
namespace FoodOrdersView
{
partial class FormMails
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
partial class FormMails
{
/// <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);
}
/// <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
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
dataGridView = new DataGridView();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(0, 0);
dataGridView.Name = "dataGridView";
dataGridView.RowTemplate.Height = 25;
dataGridView.Size = new Size(803, 450);
dataGridView.TabIndex = 0;
//
// FormMails
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Controls.Add(dataGridView);
Name = "FormMails";
Text = "Письма";
Load += FormMails_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
dataGridView = new DataGridView();
buttonPrevPage = new Button();
buttonNextPage = new Button();
labelInfoPages = new Label();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(0, 0);
dataGridView.Name = "dataGridView";
dataGridView.RowTemplate.Height = 25;
dataGridView.Size = new Size(730, 454);
dataGridView.TabIndex = 0;
dataGridView.RowHeaderMouseClick += dataGridView_RowHeaderMouseClick;
//
// buttonPrevPage
//
buttonPrevPage.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
buttonPrevPage.Location = new Point(12, 460);
buttonPrevPage.Name = "buttonPrevPage";
buttonPrevPage.Size = new Size(75, 23);
buttonPrevPage.TabIndex = 1;
buttonPrevPage.Text = "<<<";
buttonPrevPage.UseVisualStyleBackColor = true;
buttonPrevPage.Click += ButtonPrevPage_Click;
//
// buttonNextPage
//
buttonNextPage.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
buttonNextPage.Location = new Point(203, 460);
buttonNextPage.Name = "buttonNextPage";
buttonNextPage.Size = new Size(75, 23);
buttonNextPage.TabIndex = 2;
buttonNextPage.Text = ">>>";
buttonNextPage.UseVisualStyleBackColor = true;
buttonNextPage.Click += ButtonNextPage_Click;
//
// labelInfoPages
//
labelInfoPages.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
labelInfoPages.Location = new Point(93, 464);
labelInfoPages.Name = "labelInfoPages";
labelInfoPages.Size = new Size(104, 19);
labelInfoPages.TabIndex = 3;
labelInfoPages.Text = "{0} страница";
labelInfoPages.TextAlign = ContentAlignment.MiddleCenter;
//
// FormViewMail
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(727, 498);
Controls.Add(labelInfoPages);
Controls.Add(buttonNextPage);
Controls.Add(buttonPrevPage);
Controls.Add(dataGridView);
Name = "FormViewMail";
Text = "Письма";
Load += FormMails_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
#endregion
private DataGridView dataGridView;
}
private DataGridView dataGridView;
private Button buttonPrevPage;
private Button buttonNextPage;
private Label labelInfoPages;
}
}

View File

@ -1,40 +1,101 @@
using Microsoft.Extensions.Logging;
using FoodOrdersContracts.BusinessLogicsContracts;
using FoodOrdersView;
using FoodOrdersContracts.ViewModels;
namespace FoodOrdersView
{
public partial class FormMails : Form
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _logic;
public partial class FormMails : Form
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _logic;
private int currentPage = 1;
public int pageSize = 5;
public FormMails(ILogger<FormMails> logger, IMessageInfoLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
public FormMails(ILogger<FormMails> logger, IMessageInfoLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
buttonPrevPage.Enabled = false;
}
private void FormMails_Load(object sender, EventArgs e)
{
try
{
var list = _logic.ReadList(null);
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["MessageId"].Visible = false;
dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка писем");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки писем");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
}
private void FormMails_Load(object sender, EventArgs e)
{
MailLoad();
}
private bool MailLoad()
{
try
{
var list = _logic.ReadList(new()
{
Page = currentPage,
PageSize = pageSize,
});
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["MessageId"].Visible = false;
dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка списка писем");
labelInfoPages.Text = $"{currentPage} страница";
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки писем");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}
private void ButtonPrevPage_Click(object sender, EventArgs e)
{
if (currentPage == 1)
{
_logger.LogWarning("Неккоректный номер страницы {page}", currentPage - 1);
return;
}
currentPage--;
if (MailLoad())
{
buttonNextPage.Enabled = true;
if (currentPage == 1)
{
buttonPrevPage.Enabled = false;
}
}
}
private void ButtonNextPage_Click(object sender, EventArgs e)
{
currentPage++;
if (!MailLoad() || ((List<MessageInfoViewModel>)dataGridView.DataSource).Count == 0)
{
_logger.LogWarning("Out of range messages");
currentPage--;
MailLoad();
buttonNextPage.Enabled = false;
}
else
{
buttonPrevPage.Enabled = true;
}
}
private void dataGridView_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormReplyMail));
if (service is FormReplyMail form)
{
form.MessageId = (string)dataGridView.Rows[e.RowIndex].Cells["MessageId"].Value;
form.ShowDialog();
MailLoad();
}
}
}
}

View File

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

View File

@ -0,0 +1,149 @@
namespace FoodOrdersView
{
partial class FormReplyMail
{
/// <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()
{
buttonSave = new Button();
buttonCancel = new Button();
label1 = new Label();
label2 = new Label();
label3 = new Label();
textBoxHead = new TextBox();
textBoxMail = new TextBox();
textBoxReply = new TextBox();
SuspendLayout();
//
// buttonSave
//
buttonSave.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonSave.Location = new Point(460, 291);
buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(117, 30);
buttonSave.TabIndex = 0;
buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true;
buttonSave.Click += ButtonSave_Click;
//
// buttonCancel
//
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonCancel.Location = new Point(337, 291);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(117, 30);
buttonCancel.TabIndex = 1;
buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += ButtonCancel_Click;
//
// label1
//
label1.Location = new Point(12, 9);
label1.Name = "label1";
label1.Size = new Size(117, 23);
label1.TabIndex = 2;
label1.Text = "Заголовок письма:";
label1.TextAlign = ContentAlignment.TopRight;
//
// label2
//
label2.Location = new Point(12, 38);
label2.Name = "label2";
label2.Size = new Size(117, 23);
label2.TabIndex = 3;
label2.Text = "Текст письма:";
label2.TextAlign = ContentAlignment.TopRight;
//
// label3
//
label3.Location = new Point(12, 117);
label3.Name = "label3";
label3.Size = new Size(117, 31);
label3.TabIndex = 4;
label3.Text = "Ответ на письмо:";
label3.TextAlign = ContentAlignment.TopRight;
//
// textBoxHead
//
textBoxHead.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
textBoxHead.Location = new Point(135, 5);
textBoxHead.Name = "textBoxHead";
textBoxHead.ReadOnly = true;
textBoxHead.Size = new Size(442, 23);
textBoxHead.TabIndex = 5;
//
// textBoxMail
//
textBoxMail.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
textBoxMail.Location = new Point(135, 35);
textBoxMail.Multiline = true;
textBoxMail.Name = "textBoxMail";
textBoxMail.ReadOnly = true;
textBoxMail.Size = new Size(442, 76);
textBoxMail.TabIndex = 6;
//
// textBoxReply
//
textBoxReply.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
textBoxReply.Location = new Point(135, 117);
textBoxReply.Multiline = true;
textBoxReply.Name = "textBoxReply";
textBoxReply.Size = new Size(442, 168);
textBoxReply.TabIndex = 7;
//
// FormReplyMail
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(589, 333);
Controls.Add(textBoxReply);
Controls.Add(textBoxMail);
Controls.Add(textBoxHead);
Controls.Add(label3);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(buttonCancel);
Controls.Add(buttonSave);
Name = "FormReplyMail";
Text = "Ответ на письмо";
Load += FormReplyMail_Load;
ResumeLayout(false);
PerformLayout();
}
#endregion
private Button buttonSave;
private Button buttonCancel;
private Label label1;
private Label label2;
private Label label3;
private TextBox textBoxHead;
private TextBox textBoxMail;
private TextBox textBoxReply;
}
}

View File

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using FoodOrdersBusinessLogic.MailWorker;
using FoodOrdersContracts.BusinessLogicsContracts;
using FoodOrdersContracts.ViewModels;
using Microsoft.Extensions.Logging;
using MimeKit;
namespace FoodOrdersView
{
public partial class FormReplyMail : Form
{
private readonly ILogger _logger;
private readonly AbstractMailWorker _mailWorker;
private readonly IMessageInfoLogic _logic;
private MessageInfoViewModel _message;
public string MessageId { get; set; } = string.Empty;
public FormReplyMail(ILogger<FormReplyMail> logger, AbstractMailWorker mailWorker, IMessageInfoLogic logic)
{
InitializeComponent();
_logger = logger;
_mailWorker = mailWorker;
_logic = logic;
}
private void ButtonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
private void ButtonSave_Click(object sender, EventArgs e)
{
_mailWorker.MailSendAsync(new()
{
MailAddress = _message.SenderName,
Subject = _message.Subject,
Text = textBoxReply.Text,
});
_logic.Update(new()
{
MessageId = MessageId,
Reply = textBoxReply.Text,
HasRead = true,
});
MessageBox.Show("Успешно отправлено письмо", "Отправка письма", MessageBoxButtons.OK);
DialogResult = DialogResult.OK;
Close();
}
private void FormReplyMail_Load(object sender, EventArgs e)
{
try
{
_message = _logic.ReadElement(new() { MessageId = MessageId });
if (_message == null)
throw new ArgumentNullException("Письма с таким id не существует");
Text += $"для {_message.SenderName}";
textBoxHead.Text = _message.Subject;
textBoxMail.Text = _message.Body;
if (_message.HasRead is false)
{
_logic.Update(new() { MessageId = MessageId, HasRead = true, Reply = _message.Reply });
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения собщения");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
}

View File

@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -9,7 +9,6 @@ using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using FoodOrdersBusinessLogic.MailWorker;
using FoodOrdersContracts.BindingModels;
using FoodOrdersDatabaseImplement;
namespace FoodOrdersView
{
@ -106,7 +105,9 @@ namespace FoodOrdersView
services.AddTransient<FormViewImplementers>();
services.AddTransient<FormImplementer>();
services.AddTransient<FormMails>();
}
services.AddTransient<FormReplyMail>();
}
private static void MailCheck(object obj) => ServiceProvider?.GetService<AbstractMailWorker>()?.MailCheck();
}

View File

@ -6,8 +6,12 @@ namespace FoodOrdersContracts.BusinessLogicsContracts
{
public interface IMessageInfoLogic
{
List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? model);
List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? model);
bool Create(MessageInfoBindingModel model);
}
bool Create(MessageInfoBindingModel model);
bool Update(MessageInfoBindingModel model);
MessageInfoViewModel? ReadElement(MessageInfoSearchModel model);
}
}

View File

@ -13,5 +13,9 @@
string Subject { get; }
string Body { get; }
}
public bool HasRead { get; }
public string? Reply { get; }
}
}

View File

@ -9,7 +9,7 @@ namespace FoodOrdersDatabaseImplement
{
if (optionsBuilder.IsConfigured == false)
{
optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-SINQU55\SQLEXPRESS;Initial Catalog=FoodOrdersDatabase3;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True");
optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-SINQU55\SQLEXPRESS;Initial Catalog=FoodOrdersDatabaseH7;Integrated Security=True;MultipleActiveResultSets=True;TrustServerCertificate=True");
}
base.OnConfiguring(optionsBuilder);
}

View File

@ -0,0 +1,381 @@
// <auto-generated />
using System;
using FoodOrdersDatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FoodOrdersDatabaseImplement.Migrations
{
[DbContext(typeof(FoodOrdersDatabase))]
[Migration("20230429140101_H8")]
partial class H8
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Client", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClientFIO")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Clients");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Component", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ComponentName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<double>("Cost")
.HasColumnType("float");
b.HasKey("Id");
b.ToTable("Components");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Dish", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("DishName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<double>("Price")
.HasColumnType("float");
b.HasKey("Id");
b.ToTable("Dishes");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.DishComponent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("ComponentId")
.HasColumnType("int");
b.Property<int>("Count")
.HasColumnType("int");
b.Property<int>("DishId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ComponentId");
b.HasIndex("DishId");
b.ToTable("DishComponents");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Implementer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ImplementerFIO")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Qualification")
.HasColumnType("int");
b.Property<int>("WorkExperience")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Implementers");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("DateDelivery")
.HasColumnType("datetime2");
b.Property<bool>("HasRead")
.HasColumnType("bit");
b.Property<string>("Reply")
.HasColumnType("nvarchar(max)");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<int>("Count")
.HasColumnType("int");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateImplement")
.HasColumnType("datetime2");
b.Property<int>("DishId")
.HasColumnType("int");
b.Property<int?>("ImplementerId")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<double>("Sum")
.HasColumnType("float");
b.HasKey("Id");
b.HasIndex("ClientId");
b.HasIndex("DishId");
b.HasIndex("ImplementerId");
b.ToTable("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Shop", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Address")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Capacity")
.HasColumnType("int");
b.Property<DateTime>("DateOfOpening")
.HasColumnType("datetime2");
b.Property<string>("ShopName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Shops");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.ShopDish", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Count")
.HasColumnType("int");
b.Property<int>("DishId")
.HasColumnType("int");
b.Property<int>("ShopId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("DishId");
b.HasIndex("ShopId");
b.ToTable("ShopDishes");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.DishComponent", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Component", "Component")
.WithMany("DishComponents")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Dish", "Dish")
.WithMany("Components")
.HasForeignKey("DishId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("Dish");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Client", "Client")
.WithMany("Messages")
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Order", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Client", "Client")
.WithMany("Orders")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Dish", "Dish")
.WithMany("Orders")
.HasForeignKey("DishId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Implementer", "Implementer")
.WithMany("Orders")
.HasForeignKey("ImplementerId");
b.Navigation("Client");
b.Navigation("Dish");
b.Navigation("Implementer");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.ShopDish", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Dish", "Dish")
.WithMany()
.HasForeignKey("DishId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Shop", "Shop")
.WithMany("Dishes")
.HasForeignKey("ShopId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Dish");
b.Navigation("Shop");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Client", b =>
{
b.Navigation("Messages");
b.Navigation("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Component", b =>
{
b.Navigation("DishComponents");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Dish", b =>
{
b.Navigation("Components");
b.Navigation("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Shop", b =>
{
b.Navigation("Dishes");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,275 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FoodOrdersDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class H8 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Clients",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ClientFIO = table.Column<string>(type: "nvarchar(max)", nullable: false),
Email = table.Column<string>(type: "nvarchar(max)", nullable: false),
Password = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Clients", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Components",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ComponentName = table.Column<string>(type: "nvarchar(max)", nullable: false),
Cost = table.Column<double>(type: "float", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Components", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Dishes",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
DishName = table.Column<string>(type: "nvarchar(max)", nullable: false),
Price = table.Column<double>(type: "float", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Dishes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Implementers",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ImplementerFIO = table.Column<string>(type: "nvarchar(max)", nullable: false),
Password = table.Column<string>(type: "nvarchar(max)", nullable: false),
WorkExperience = table.Column<int>(type: "int", nullable: false),
Qualification = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Implementers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Shops",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ShopName = table.Column<string>(type: "nvarchar(max)", nullable: false),
Address = table.Column<string>(type: "nvarchar(max)", nullable: false),
DateOfOpening = table.Column<DateTime>(type: "datetime2", nullable: false),
Capacity = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Shops", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Messages",
columns: table => new
{
MessageId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClientId = table.Column<int>(type: "int", nullable: true),
SenderName = table.Column<string>(type: "nvarchar(max)", nullable: false),
DateDelivery = table.Column<DateTime>(type: "datetime2", nullable: false),
Subject = table.Column<string>(type: "nvarchar(max)", nullable: false),
Body = table.Column<string>(type: "nvarchar(max)", nullable: false),
HasRead = table.Column<bool>(type: "bit", nullable: false),
Reply = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
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: "DishComponents",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
DishId = table.Column<int>(type: "int", nullable: false),
ComponentId = table.Column<int>(type: "int", nullable: false),
Count = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DishComponents", x => x.Id);
table.ForeignKey(
name: "FK_DishComponents_Components_ComponentId",
column: x => x.ComponentId,
principalTable: "Components",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DishComponents_Dishes_DishId",
column: x => x.DishId,
principalTable: "Dishes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Orders",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
DishId = table.Column<int>(type: "int", nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false),
ImplementerId = table.Column<int>(type: "int", nullable: true),
Count = table.Column<int>(type: "int", nullable: false),
Sum = table.Column<double>(type: "float", nullable: false),
Status = table.Column<int>(type: "int", nullable: false),
DateCreate = table.Column<DateTime>(type: "datetime2", nullable: false),
DateImplement = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Orders", x => x.Id);
table.ForeignKey(
name: "FK_Orders_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Orders_Dishes_DishId",
column: x => x.DishId,
principalTable: "Dishes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Orders_Implementers_ImplementerId",
column: x => x.ImplementerId,
principalTable: "Implementers",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "ShopDishes",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ShopId = table.Column<int>(type: "int", nullable: false),
DishId = table.Column<int>(type: "int", nullable: false),
Count = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShopDishes", x => x.Id);
table.ForeignKey(
name: "FK_ShopDishes_Dishes_DishId",
column: x => x.DishId,
principalTable: "Dishes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ShopDishes_Shops_ShopId",
column: x => x.ShopId,
principalTable: "Shops",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_DishComponents_ComponentId",
table: "DishComponents",
column: "ComponentId");
migrationBuilder.CreateIndex(
name: "IX_DishComponents_DishId",
table: "DishComponents",
column: "DishId");
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_DishId",
table: "Orders",
column: "DishId");
migrationBuilder.CreateIndex(
name: "IX_Orders_ImplementerId",
table: "Orders",
column: "ImplementerId");
migrationBuilder.CreateIndex(
name: "IX_ShopDishes_DishId",
table: "ShopDishes",
column: "DishId");
migrationBuilder.CreateIndex(
name: "IX_ShopDishes_ShopId",
table: "ShopDishes",
column: "ShopId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DishComponents");
migrationBuilder.DropTable(
name: "Messages");
migrationBuilder.DropTable(
name: "Orders");
migrationBuilder.DropTable(
name: "ShopDishes");
migrationBuilder.DropTable(
name: "Components");
migrationBuilder.DropTable(
name: "Clients");
migrationBuilder.DropTable(
name: "Implementers");
migrationBuilder.DropTable(
name: "Dishes");
migrationBuilder.DropTable(
name: "Shops");
}
}
}

View File

@ -0,0 +1,378 @@
// <auto-generated />
using System;
using FoodOrdersDatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FoodOrdersDatabaseImplement.Migrations
{
[DbContext(typeof(FoodOrdersDatabase))]
partial class FoodOrdersDatabaseModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Client", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClientFIO")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Clients");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Component", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ComponentName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<double>("Cost")
.HasColumnType("float");
b.HasKey("Id");
b.ToTable("Components");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Dish", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("DishName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<double>("Price")
.HasColumnType("float");
b.HasKey("Id");
b.ToTable("Dishes");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.DishComponent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("ComponentId")
.HasColumnType("int");
b.Property<int>("Count")
.HasColumnType("int");
b.Property<int>("DishId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ComponentId");
b.HasIndex("DishId");
b.ToTable("DishComponents");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Implementer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ImplementerFIO")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Qualification")
.HasColumnType("int");
b.Property<int>("WorkExperience")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Implementers");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("DateDelivery")
.HasColumnType("datetime2");
b.Property<bool>("HasRead")
.HasColumnType("bit");
b.Property<string>("Reply")
.HasColumnType("nvarchar(max)");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<int>("Count")
.HasColumnType("int");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateImplement")
.HasColumnType("datetime2");
b.Property<int>("DishId")
.HasColumnType("int");
b.Property<int?>("ImplementerId")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<double>("Sum")
.HasColumnType("float");
b.HasKey("Id");
b.HasIndex("ClientId");
b.HasIndex("DishId");
b.HasIndex("ImplementerId");
b.ToTable("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Shop", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Address")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Capacity")
.HasColumnType("int");
b.Property<DateTime>("DateOfOpening")
.HasColumnType("datetime2");
b.Property<string>("ShopName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Shops");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.ShopDish", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Count")
.HasColumnType("int");
b.Property<int>("DishId")
.HasColumnType("int");
b.Property<int>("ShopId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("DishId");
b.HasIndex("ShopId");
b.ToTable("ShopDishes");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.DishComponent", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Component", "Component")
.WithMany("DishComponents")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Dish", "Dish")
.WithMany("Components")
.HasForeignKey("DishId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("Dish");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Client", "Client")
.WithMany("Messages")
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Order", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Client", "Client")
.WithMany("Orders")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Dish", "Dish")
.WithMany("Orders")
.HasForeignKey("DishId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Implementer", "Implementer")
.WithMany("Orders")
.HasForeignKey("ImplementerId");
b.Navigation("Client");
b.Navigation("Dish");
b.Navigation("Implementer");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.ShopDish", b =>
{
b.HasOne("FoodOrdersDatabaseImplement.Models.Dish", "Dish")
.WithMany()
.HasForeignKey("DishId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodOrdersDatabaseImplement.Models.Shop", "Shop")
.WithMany("Dishes")
.HasForeignKey("ShopId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Dish");
b.Navigation("Shop");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Client", b =>
{
b.Navigation("Messages");
b.Navigation("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Component", b =>
{
b.Navigation("DishComponents");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Dish", b =>
{
b.Navigation("Components");
b.Navigation("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Orders");
});
modelBuilder.Entity("FoodOrdersDatabaseImplement.Models.Shop", b =>
{
b.Navigation("Dishes");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -23,7 +23,10 @@ namespace FoodOrdersDatabaseImplement.Models
[ForeignKey("ClientId")]
public virtual List<Order> Orders { get; set; } = new();
public static Client? Create(ClientBindingModel? model)
[ForeignKey("ClientId")]
public virtual List<MessageInfo> Messages { get; set; } = new();
public static Client? Create(ClientBindingModel? model)
{
if (model == null)
{

View File

@ -36,10 +36,7 @@ namespace FoodOrdersDatabaseImplement.Models
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
ClientId = model.ClientId,
SenderName = model.SenderName,
Body = model.Body,
Subject = model.Subject,
DateDelivery = model.DateDelivery,
};
}
@ -61,10 +58,7 @@ namespace FoodOrdersDatabaseImplement.Models
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
Body = Body,
Subject = Subject,
DateDelivery = DateDelivery,
};
}

View File

@ -52,7 +52,13 @@ namespace FoodOrdersFileImplement.Implements
public MessageInfoViewModel? Update(MessageInfoBindingModel model)
{
throw new NotImplementedException();
var res = _source.Messages.FirstOrDefault(x => x.MessageId.Equals(model.MessageId));
if (res != null)
{
res.Update(model);
_source.SaveMessages();
}
return res?.GetViewModel;
}
}
}

View File

@ -27,6 +27,8 @@ namespace FoodOrdersFileImplement.Models
[DataMember]
public string Body { get; private set; } = string.Empty;
public bool HasRead { get; private set; }
public string? Reply { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
@ -36,13 +38,15 @@ namespace FoodOrdersFileImplement.Models
}
return new()
{
Body = model.Body,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
};
Body = model.Body,
Reply = model.Reply,
HasRead = model.HasRead,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
};
}
public static MessageInfo? Create(XElement element)
@ -53,35 +57,49 @@ namespace FoodOrdersFileImplement.Models
}
return new()
{
Body = element.Attribute("Body")!.Value,
Subject = element.Attribute("Subject")!.Value,
ClientId = Convert.ToInt32(element.Attribute("ClientId")!.Value),
MessageId = element.Attribute("MessageId")!.Value,
SenderName = element.Attribute("SenderName")!.Value,
DateDelivery = Convert.ToDateTime(element.Attribute("DateDelivery")!.Value),
};
Body = element.Attribute("Body")!.Value,
Reply = element.Attribute("Reply")!.Value,
HasRead = Convert.ToBoolean(element.Attribute("HasRead")!.Value),
Subject = element.Attribute("Subject")!.Value,
ClientId = Convert.ToInt32(element.Attribute("ClientId")!.Value),
MessageId = element.Attribute("MessageId")!.Value,
SenderName = element.Attribute("SenderName")!.Value,
DateDelivery = Convert.ToDateTime(element.Attribute("DateDelivery")!.Value),
};
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
public void Update(MessageInfoBindingModel model)
{
if (model == null)
{
return;
}
Reply = model.Reply;
HasRead = model.HasRead;
}
public XElement GetXElement => new("MessageInfo",
new XAttribute("Body", Body),
new XAttribute("Subject", Subject),
new XAttribute("ClientId", ClientId),
new XAttribute("MessageId", MessageId),
new XAttribute("SenderName", SenderName),
new XAttribute("DateDelivery", DateDelivery)
);
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Reply = Reply,
HasRead = HasRead,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
public int Id => throw new NotImplementedException();
public XElement GetXElement => new("MessageInfo",
new XAttribute("Body", Body),
new XAttribute("Reply", Reply),
new XAttribute("HasRead", HasRead),
new XAttribute("Subject", Subject),
new XAttribute("ClientId", ClientId),
new XAttribute("MessageId", MessageId),
new XAttribute("SenderName", SenderName),
new XAttribute("DateDelivery", DateDelivery)
);
}
}

View File

@ -60,7 +60,15 @@ namespace FoodOrdersListImplement.Implements
public MessageInfoViewModel? Update(MessageInfoBindingModel model)
{
throw new NotImplementedException();
foreach (var message in _source.Messages)
{
if (message.MessageId.Equals(model.MessageId))
{
message.Update(model);
return message.GetViewModel;
}
}
return null;
}
}
}

View File

@ -19,7 +19,10 @@ namespace FoodOrdersListImplement.Models
public string Body { get; private set; } = string.Empty;
public static MessageInfo? Create(MessageInfoBindingModel model)
public bool HasRead { get; private set; }
public string? Reply { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
if (model == null)
{
@ -27,26 +30,38 @@ namespace FoodOrdersListImplement.Models
}
return new()
{
Body = model.Body,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
};
Body = model.Body,
Reply = model.Reply,
HasRead = model.HasRead,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
};
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
public void Update(MessageInfoBindingModel model)
{
if (model == null)
{
return;
}
Reply = model.Reply;
HasRead = model.HasRead;
}
public int Id => throw new NotImplementedException();
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Reply = Reply,
HasRead = HasRead,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
}
}

View File

@ -16,7 +16,9 @@ namespace FoodOrdersRestApi.Controllers
private readonly IMessageInfoLogic _mailLogic;
public ClientController(IClientLogic logic, IMessageInfoLogic mailLogic, ILogger<ClientController> logger)
public int pageSize = 3;
public ClientController(IClientLogic logic, IMessageInfoLogic mailLogic, ILogger<ClientController> logger)
{
_logger = logger;
_logic = logic;
@ -70,14 +72,16 @@ namespace FoodOrdersRestApi.Controllers
}
[HttpGet]
public List<MessageInfoViewModel>? GetMessages(int clientId)
public List<MessageInfoViewModel>? GetMessages(int clientId, int page)
{
try
{
return _mailLogic.ReadList(new MessageInfoSearchModel
{
ClientId = clientId
});
ClientId = clientId,
Page = page,
PageSize = pageSize
});
}
catch (Exception ex)
{