Agliullov D. A. Lab Work 7 Hard #20

Closed
d.agliullov wants to merge 34 commits from Lab7_Hard into Lab6_Hard
14 changed files with 575 additions and 38 deletions
Showing only changes of commit 8e6c287547 - Show all commits

View File

@ -29,7 +29,16 @@ namespace ConfectioneryBusinessLogic.MailWorker
objMailMessage.Body = info.Text;
objMailMessage.SubjectEncoding = Encoding.UTF8;
objMailMessage.BodyEncoding = Encoding.UTF8;
if (info.MessageId != null)
{
objMailMessage.Headers.Add("Message-Id", info.MessageId);
}
if (info.ReplyMessageId != null)
{
objMailMessage.Headers.Add("In-Reply-To", info.ReplyMessageId);
objMailMessage.Headers.Add("References", info.ReplyMessageId);
}
objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true;
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;

View File

@ -25,7 +25,7 @@ namespace ConfectioneryFileImplement.Models
public string Body { get; private set; } = string.Empty;
public bool HasRead { get; private set; }
public string? Reply { get; private set; }
public string? ReplyMessageId { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
@ -36,13 +36,13 @@ namespace ConfectioneryFileImplement.Models
return new()
{
Body = model.Body,
Reply = model.Reply,
HasRead = model.HasRead,
HasRead = model.HasRead,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
ReplyMessageId = model.ReplyMessageId,
};
}
@ -55,13 +55,13 @@ namespace ConfectioneryFileImplement.Models
return new()
{
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),
ReplyMessageId = element.Attribute("ReplyMessageId")!.Value,
};
}
@ -71,25 +71,28 @@ namespace ConfectioneryFileImplement.Models
{
return;
}
Reply = model.Reply;
ReplyMessageId = model.ReplyMessageId;
HasRead = model.HasRead;
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Reply = Reply,
HasRead = HasRead,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
ReplyMessageId = ReplyMessageId,
ReplyText = DataFileSingleton.GetInstance().Messages
.FirstOrDefault(x => ReplyMessageId != null && ReplyMessageId.Equals(x.MessageId))
?.Body ?? string.Empty,
};
public XElement GetXElement => new("MessageInfo",
new XAttribute("Body", Body),
new XAttribute("Reply", Reply),
new XAttribute("ReplyMessageId", ReplyMessageId),
new XAttribute("HasRead", HasRead),
new XAttribute("Subject", Subject),
new XAttribute("ClientId", ClientId),

View File

@ -24,7 +24,7 @@ namespace ConfectioneryListImplement.Models
public string Body { get; private set; } = string.Empty;
public bool HasRead { get; private set; }
public string? Reply { get; private set; }
public string? ReplyMessageId { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
@ -35,13 +35,13 @@ namespace ConfectioneryListImplement.Models
return new()
{
Body = model.Body,
Reply = model.Reply,
HasRead = model.HasRead,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
ReplyMessageId = model.ReplyMessageId,
};
}
@ -51,22 +51,40 @@ namespace ConfectioneryListImplement.Models
{
return;
}
Reply = model.Reply;
ReplyMessageId = model.MessageId;
HasRead = model.HasRead;
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Reply = Reply,
HasRead = HasRead,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
public MessageInfoViewModel GetViewModel
{
get
{
var res = new MessageInfoViewModel()
{
Body = Body,
HasRead = HasRead,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
ReplyMessageId = ReplyMessageId,
};
if (ReplyMessageId != null)
{
foreach (var msg in DataListSingleton.GetInstance().Messages)
{
if (msg.MessageId.Equals(ReplyMessageId))
{
res.ReplyText = msg.Body;
return res;
}
}
}
}
return res;
}
}
}
}

View File

@ -40,17 +40,29 @@ namespace ConfectioneryView
private void ButtonSave_Click(object sender, EventArgs e)
{
var guid = Guid.NewGuid();
var newMsgId = $"<{guid.ToString().Replace("-", "")}@f129.i.mail.ru>";
_mailWorker.MailSendAsync(new()
{
MessageId = newMsgId,
ReplyMessageId = _message.MessageId,
MailAddress = _message.SenderName,
Subject = _message.Subject,
Text = textBoxReply.Text,
});
_logic.Create(new()
{
MessageId = newMsgId,
Body = textBoxReply.Text,
ClientId = _message.ClientId,
HasRead = false,
Subject = _message.Subject,
});
_logic.Update(new()
{
MessageId = MessageId,
Reply = textBoxReply.Text,
HasRead = true,
ReplyMessageId = newMsgId,
});
MessageBox.Show("Успешно отправлено письмо", "Отправка письма", MessageBoxButtons.OK);
DialogResult = DialogResult.OK;

View File

@ -47,7 +47,7 @@ namespace ConfectioneryView
{
dataGridView.DataSource = list;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["MessageId"].Visible = false;
dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка списка писем");

View File

@ -8,6 +8,9 @@ namespace ConfectioneryContracts.BindingModels
{
public class MailSendInfoBindingModel
{
public string? MessageId { get; set; } = string.Empty;
public string? ReplyMessageId { get; set; } = string.Empty;
public string MailAddress { get; set; } = string.Empty;
public string Subject { get; set; } = string.Empty;
public string Text { get; set; } = string.Empty;

View File

@ -22,6 +22,6 @@ namespace ConfectioneryContracts.BindingModels
public DateTime DateDelivery { get; set; }
public bool HasRead { get; set; }
public string? Reply { get; set; }
public string? ReplyMessageId { get; set; }
}
}

View File

@ -29,7 +29,9 @@ namespace ConfectioneryContracts.ViewModels
[DisplayName("Прочитано")]
public bool HasRead { get; set; }
[DisplayName("Ответ")]
public string? Reply { get; set; }
[DisplayName("Ответ")]
public string ReplyText { get; set; } = string.Empty;
public string? ReplyMessageId { get; set; }
}
}

View File

@ -22,6 +22,6 @@ namespace ConfectioneryDataModels
public bool HasRead { get; }
public string? Reply { get; }
public string? ReplyMessageId { get; }
}
}

View File

@ -23,8 +23,12 @@ namespace ConfectioneryDatabaseImplement.Models
public Client? Client { get; private set; }
public MessageInfo? ReplyMessage { get; private set; }
public List<MessageInfo> Messages { get; private set; } = new();
public bool HasRead { get; private set; }
public string? Reply { get; private set; }
public string? ReplyMessageId { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
@ -35,13 +39,13 @@ namespace ConfectioneryDatabaseImplement.Models
return new()
{
Body = model.Body,
Reply = model.Reply,
HasRead = model.HasRead,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
ReplyMessageId = model.ReplyMessageId,
};
}
@ -51,21 +55,23 @@ namespace ConfectioneryDatabaseImplement.Models
{
return;
}
Reply = model.Reply;
ReplyMessageId = ReplyMessageId;
HasRead = model.HasRead;
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Reply = Reply,
HasRead = HasRead,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
ReplyMessageId = ReplyMessageId,
ReplyText = ReplyMessage?.Body ?? string.Empty,
};
}

View File

@ -3,6 +3,7 @@ using ConfectioneryContracts.SearchModels;
using ConfectioneryContracts.StoragesContract;
using ConfectioneryContracts.ViewModels;
using ConfectioneryDatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;
namespace ConfectioneryDatabaseImplement
{
@ -14,7 +15,9 @@ namespace ConfectioneryDatabaseImplement
using var context = new ConfectioneryDatabase();
if (model.MessageId != null)
{
return context.Messages.FirstOrDefault(x => x.MessageId == model.MessageId)?.GetViewModel;
return context.Messages
.Include(x => x.ReplyMessage)
.FirstOrDefault(x => x.MessageId == model.MessageId)?.GetViewModel;
}
return null;
}
@ -23,7 +26,8 @@ namespace ConfectioneryDatabaseImplement
{
using var context = new ConfectioneryDatabase();
var res = context.Messages
.Where(x => !model.ClientId.HasValue || x.ClientId == model.ClientId)
.Include(x => x.ReplyMessage)
.Where(x => !model.ClientId.HasValue || x.ClientId == model.ClientId)
.Select(x => x.GetViewModel);
if (!(model.Page.HasValue && model.PageSize.HasValue))
{
@ -36,7 +40,8 @@ namespace ConfectioneryDatabaseImplement
{
using var context = new ConfectioneryDatabase();
return context.Messages
.Select(x => x.GetViewModel)
.Include(x => x.ReplyMessage)
.Select(x => x.GetViewModel)
.ToList();
}

View File

@ -0,0 +1,408 @@
// <auto-generated />
using System;
using ConfectioneryDatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ConfectioneryDatabaseImplement.Migrations
{
[DbContext(typeof(ConfectioneryDatabase))]
[Migration("20230318021140_add_self_reply_message")]
partial class add_self_reply_message
{
/// <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("ConfectioneryDatabaseImplement.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("ConfectioneryDatabaseImplement.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("ConfectioneryDatabaseImplement.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("ConfectioneryDatabaseImplement.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>("ReplyMessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.HasIndex("ReplyMessageId");
b.ToTable("Messages");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.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?>("ImplementerId")
.HasColumnType("int");
b.Property<int>("PastryId")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<double>("Sum")
.HasColumnType("float");
b.HasKey("Id");
b.HasIndex("ClientId");
b.HasIndex("ImplementerId");
b.HasIndex("PastryId");
b.ToTable("Orders");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Pastry", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("PastryName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<double>("Price")
.HasColumnType("float");
b.HasKey("Id");
b.ToTable("Pastries");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.PastryComponent", 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>("PastryId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ComponentId");
b.HasIndex("PastryId");
b.ToTable("PastryComponents");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.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<DateTime>("DateOpening")
.HasColumnType("datetime2");
b.Property<int>("MaxCountPastries")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("PastryId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PastryId");
b.ToTable("Shops");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.ShopPastry", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Count")
.HasColumnType("int");
b.Property<int>("PastryId")
.HasColumnType("int");
b.Property<int>("ShopId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PastryId");
b.HasIndex("ShopId");
b.ToTable("ShopPastries");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("ConfectioneryDatabaseImplement.Models.Client", "Client")
.WithMany("Messages")
.HasForeignKey("ClientId");
b.HasOne("ConfectioneryDatabaseImplement.Models.MessageInfo", "ReplyMessage")
.WithMany("Messages")
.HasForeignKey("ReplyMessageId");
b.Navigation("Client");
b.Navigation("ReplyMessage");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Order", b =>
{
b.HasOne("ConfectioneryDatabaseImplement.Models.Client", "Client")
.WithMany("Orders")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ConfectioneryDatabaseImplement.Models.Implementer", "Implementer")
.WithMany("Orders")
.HasForeignKey("ImplementerId");
b.HasOne("ConfectioneryDatabaseImplement.Models.Pastry", "Pastry")
.WithMany("Orders")
.HasForeignKey("PastryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
b.Navigation("Implementer");
b.Navigation("Pastry");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.PastryComponent", b =>
{
b.HasOne("ConfectioneryDatabaseImplement.Models.Component", "Component")
.WithMany("PastryComponents")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ConfectioneryDatabaseImplement.Models.Pastry", "Pastry")
.WithMany("Components")
.HasForeignKey("PastryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("Pastry");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Shop", b =>
{
b.HasOne("ConfectioneryDatabaseImplement.Models.Pastry", null)
.WithMany("Shops")
.HasForeignKey("PastryId");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.ShopPastry", b =>
{
b.HasOne("ConfectioneryDatabaseImplement.Models.Pastry", "Pastry")
.WithMany()
.HasForeignKey("PastryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ConfectioneryDatabaseImplement.Models.Shop", "Shop")
.WithMany("ShopPastries")
.HasForeignKey("ShopId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Pastry");
b.Navigation("Shop");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Client", b =>
{
b.Navigation("Messages");
b.Navigation("Orders");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Component", b =>
{
b.Navigation("PastryComponents");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Orders");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.MessageInfo", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Pastry", b =>
{
b.Navigation("Components");
b.Navigation("Orders");
b.Navigation("Shops");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Shop", b =>
{
b.Navigation("ShopPastries");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,58 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ConfectioneryDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class add_self_reply_message : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Reply",
table: "Messages");
migrationBuilder.AddColumn<string>(
name: "ReplyMessageId",
table: "Messages",
type: "nvarchar(450)",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_Messages_ReplyMessageId",
table: "Messages",
column: "ReplyMessageId");
migrationBuilder.AddForeignKey(
name: "FK_Messages_Messages_ReplyMessageId",
table: "Messages",
column: "ReplyMessageId",
principalTable: "Messages",
principalColumn: "MessageId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Messages_Messages_ReplyMessageId",
table: "Messages");
migrationBuilder.DropIndex(
name: "IX_Messages_ReplyMessageId",
table: "Messages");
migrationBuilder.DropColumn(
name: "ReplyMessageId",
table: "Messages");
migrationBuilder.AddColumn<string>(
name: "Reply",
table: "Messages",
type: "nvarchar(max)",
nullable: true);
}
}
}

View File

@ -112,8 +112,8 @@ namespace ConfectioneryDatabaseImplement.Migrations
b.Property<bool>("HasRead")
.HasColumnType("bit");
b.Property<string>("Reply")
.HasColumnType("nvarchar(max)");
b.Property<string>("ReplyMessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("SenderName")
.IsRequired()
@ -127,6 +127,8 @@ namespace ConfectioneryDatabaseImplement.Migrations
b.HasIndex("ClientId");
b.HasIndex("ReplyMessageId");
b.ToTable("Messages");
});
@ -283,7 +285,13 @@ namespace ConfectioneryDatabaseImplement.Migrations
.WithMany("Messages")
.HasForeignKey("ClientId");
b.HasOne("ConfectioneryDatabaseImplement.Models.MessageInfo", "ReplyMessage")
.WithMany("Messages")
.HasForeignKey("ReplyMessageId");
b.Navigation("Client");
b.Navigation("ReplyMessage");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Order", b =>
@ -373,6 +381,11 @@ namespace ConfectioneryDatabaseImplement.Migrations
b.Navigation("Orders");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.MessageInfo", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Pastry", b =>
{
b.Navigation("Components");