This commit is contained in:
DeerElk 2024-05-08 11:57:33 +04:00
parent c9705c72f1
commit 80027002c2
36 changed files with 891 additions and 110 deletions

View File

@ -0,0 +1,81 @@
namespace ConfectioneryView
{
partial class FormClients
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer Clients = 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 && (Clients != null))
{
Clients.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
dataGridView = new DataGridView();
buttonDel = new Button();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// DataGridView
//
dataGridView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
dataGridView.BackgroundColor = SystemColors.Window;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(0, 0);
dataGridView.Margin = new Padding(4);
dataGridView.Name = "dataGridView";
dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 29;
dataGridView.Size = new Size(742, 444);
dataGridView.TabIndex = 0;
//
// buttonDel
//
buttonDel.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonDel.Location = new Point(754, 198);
buttonDel.Margin = new Padding(4);
buttonDel.Name = "buttonDel";
buttonDel.Size = new Size(112, 56);
buttonDel.TabIndex = 3;
buttonDel.Text = "Удалить";
buttonDel.UseVisualStyleBackColor = true;
buttonDel.Click += ButtonDel_Click;
//
// FormClients
//
AutoScaleDimensions = new SizeF(10F, 25F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(878, 444);
Controls.Add(buttonDel);
Controls.Add(dataGridView);
Margin = new Padding(4);
Name = "FormPastries";
Text = "Клиенты";
Load += FormClients_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
private Button buttonDel;
}
}

View File

@ -0,0 +1,78 @@
using ConfectioneryContracts.BindingModels;
using ConfectioneryContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
namespace ConfectioneryView
{
public partial class FormClients : Form
{
private readonly ILogger _logger;
private readonly IClientLogic _logic;
public FormClients(ILogger<FormClients> logger, IClientLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
private void LoadData()
{
try
{
var list = _logic.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;
}
_logger.LogInformation("Загрузка клиентов");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки клиентов");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private void FormClients_Load(object sender, EventArgs e)
{
LoadData();
}
private void ButtonDel_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
if (MessageBox.Show("Удалить запись?", "Вопрос",
MessageBoxButtons.YesNo, MessageBoxIcon.Question)
== DialogResult.Yes)
{
int id = Convert.ToInt32(
dataGridView.SelectedRows[0].Cells["Id"].Value);
_logger.LogInformation("Удаление клиента");
try
{
if (!_logic.Delete(new ClientBindingModel
{
Id = id
}))
{
throw new Exception("Ошибка при удалении. " +
"Дополнительная информация в логах.");
}
LoadData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка удаления компонента");
MessageBox.Show(ex.Message, "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
}

View File

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

View File

@ -36,12 +36,14 @@
textBoxSum = new TextBox();
buttonSave = new Button();
buttonCancel = new Button();
labelClient = new Label();
comboBoxClient = new ComboBox();
SuspendLayout();
//
// labelPastry
//
labelPastry.AutoSize = true;
labelPastry.Location = new Point(16, 21);
labelPastry.Location = new Point(16, 14);
labelPastry.Name = "labelPastry";
labelPastry.Size = new Size(84, 25);
labelPastry.TabIndex = 0;
@ -50,7 +52,7 @@
// labelCount
//
labelCount.AutoSize = true;
labelCount.Location = new Point(16, 66);
labelCount.Location = new Point(16, 61);
labelCount.Name = "labelCount";
labelCount.Size = new Size(111, 25);
labelCount.TabIndex = 1;
@ -59,7 +61,7 @@
// labelSum
//
labelSum.AutoSize = true;
labelSum.Location = new Point(16, 112);
labelSum.Location = new Point(16, 153);
labelSum.Name = "labelSum";
labelSum.Size = new Size(71, 25);
labelSum.TabIndex = 2;
@ -70,7 +72,7 @@
comboBoxPastry.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
comboBoxPastry.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoxPastry.FormattingEnabled = true;
comboBoxPastry.Location = new Point(170, 21);
comboBoxPastry.Location = new Point(170, 11);
comboBoxPastry.Name = "comboBoxPastry";
comboBoxPastry.Size = new Size(396, 33);
comboBoxPastry.TabIndex = 3;
@ -79,7 +81,7 @@
// textBoxCount
//
textBoxCount.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
textBoxCount.Location = new Point(170, 66);
textBoxCount.Location = new Point(170, 57);
textBoxCount.Name = "textBoxCount";
textBoxCount.Size = new Size(396, 31);
textBoxCount.TabIndex = 4;
@ -88,10 +90,10 @@
// textBoxSum
//
textBoxSum.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
textBoxSum.Location = new Point(170, 112);
textBoxSum.Location = new Point(170, 149);
textBoxSum.Name = "textBoxSum";
textBoxSum.ReadOnly = true;
textBoxSum.Size = new Size(396, 31);
textBoxSum.Size = new Size(159, 31);
textBoxSum.TabIndex = 5;
//
// buttonSave
@ -116,6 +118,24 @@
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += ButtonCancel_Click;
//
// labelClient
//
labelClient.AutoSize = true;
labelClient.Location = new Point(16, 108);
labelClient.Name = "labelClient";
labelClient.Size = new Size(71, 25);
labelClient.TabIndex = 8;
labelClient.Text = "Клиент:";
//
// comboBoxClient
//
comboBoxClient.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoxClient.FormattingEnabled = true;
comboBoxClient.Location = new Point(170, 102);
comboBoxClient.Name = "comboBoxClient";
comboBoxClient.Size = new Size(396, 33);
comboBoxClient.TabIndex = 9;
//
// FormCreateOrder
//
AutoScaleDimensions = new SizeF(10F, 25F);
@ -129,6 +149,8 @@
Controls.Add(labelSum);
Controls.Add(labelCount);
Controls.Add(labelPastry);
Controls.Add(comboBoxClient);
Controls.Add(labelClient);
Name = "FormCreateOrder";
Text = "Создание заказа";
Load += FormCreateOrder_Load;
@ -146,5 +168,7 @@
private TextBox textBoxSum;
private Button buttonSave;
private Button buttonCancel;
private Label labelClient;
private ComboBox comboBoxClient;
}
}

View File

@ -9,13 +9,15 @@ namespace ConfectioneryView
private readonly ILogger _logger;
private readonly IPastryLogic _logicP;
private readonly IOrderLogic _logicO;
private readonly IClientLogic _logicC;
public FormCreateOrder(ILogger<FormCreateOrder> logger,
IPastryLogic logicP, IOrderLogic logicO)
IPastryLogic logicP, IOrderLogic logicO, IClientLogic logicC)
{
InitializeComponent();
_logger = logger;
_logicP = logicP;
_logicO = logicO;
_logicC = logicC;
}
private void FormCreateOrder_Load(object sender, EventArgs e)
{
@ -38,6 +40,25 @@ namespace ConfectioneryView
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
_logger.LogInformation("Загрузка клиентов для заказа");
try
{
var list = _logicC.ReadList(null);
if (list != null)
{
comboBoxClient.DisplayMember = "ClientFIO";
comboBoxClient.ValueMember = "Id";
comboBoxClient.DataSource = list;
comboBoxClient.SelectedItem = null;
}
_logger.LogInformation("Клиенты загружены");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки клиентов");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private void CalcSum()
{
@ -87,12 +108,19 @@ namespace ConfectioneryView
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (comboBoxClient.SelectedValue == null)
{
MessageBox.Show("Выберите клиента", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Создание заказа");
try
{
var operationResult = _logicO.CreateOrder(new OrderBindingModel
{
PastryId = Convert.ToInt32(comboBoxPastry.SelectedValue),
ClientId = Convert.ToInt32(comboBoxClient.SelectedValue),
Count = Convert.ToInt32(textBoxCount.Text),
Sum = Convert.ToDouble(textBoxSum.Text)
});

View File

@ -38,6 +38,7 @@
referencesToolStripMenuItem = new ToolStripMenuItem();
componentsToolStripMenuItem = new ToolStripMenuItem();
pastriesToolStripMenuItem = new ToolStripMenuItem();
clientsToolStripMenuItem = new ToolStripMenuItem();
отчётыToolStripMenuItem = new ToolStripMenuItem();
listOfComponentsToolStripMenuItem = new ToolStripMenuItem();
ComponentsByPastryToolStripMenuItem = new ToolStripMenuItem();
@ -119,13 +120,13 @@
menuStrip.Items.AddRange(new ToolStripItem[] { referencesToolStripMenuItem, отчётыToolStripMenuItem });
menuStrip.Location = new Point(0, 0);
menuStrip.Name = "menuStrip";
menuStrip.Size = new Size(235, 33);
menuStrip.Size = new Size(415, 33);
menuStrip.TabIndex = 8;
menuStrip.Text = "menuStrip1";
//
// referencesToolStripMenuItem
//
referencesToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, pastriesToolStripMenuItem });
referencesToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, pastriesToolStripMenuItem, clientsToolStripMenuItem });
referencesToolStripMenuItem.Name = "referencesToolStripMenuItem";
referencesToolStripMenuItem.Size = new Size(139, 29);
referencesToolStripMenuItem.Text = "Справочники";
@ -144,6 +145,13 @@
pastriesToolStripMenuItem.Text = "Кондитерские изделия";
pastriesToolStripMenuItem.Click += PastriesToolStripMenuItem_Click;
//
// clientsToolStripMenuItem
//
clientsToolStripMenuItem.Name = "clientsToolStripMenuItem";
clientsToolStripMenuItem.Size = new Size(298, 34);
clientsToolStripMenuItem.Text = "Клиенты";
clientsToolStripMenuItem.Click += ClientsToolStripMenuItem_Click;
//
// отчётыToolStripMenuItem
//
отчётыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { listOfComponentsToolStripMenuItem, ComponentsByPastryToolStripMenuItem, listOfOrdersToolStripMenuItem });
@ -211,5 +219,6 @@
private ToolStripMenuItem listOfComponentsToolStripMenuItem;
private ToolStripMenuItem ComponentsByPastryToolStripMenuItem;
private ToolStripMenuItem listOfOrdersToolStripMenuItem;
private ToolStripMenuItem clientsToolStripMenuItem;
}
}

View File

@ -32,6 +32,7 @@ namespace ConfectioneryView
{
dataGridView.DataSource = list;
dataGridView.Columns["PastryId"].Visible = false;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["PastryName"].AutoSizeMode =
DataGridViewAutoSizeColumnMode.None;
}
@ -64,6 +65,15 @@ namespace ConfectioneryView
form.ShowDialog();
}
}
private void ClientsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(
typeof(FormClients));
if (service is FormClients form)
{
form.ShowDialog();
}
}
private void ListOfComponentsToolStripMenuItem_Click(object sender,
EventArgs e)
{
@ -203,6 +213,8 @@ namespace ConfectioneryView
Id = id,
PastryId = Convert.ToInt32(dataGridView.SelectedRows[
0].Cells["PastryId"].Value),
ClientId = Convert.ToInt32(dataGridView.SelectedRows[
0].Cells["ClientId"].Value),
Status = Enum.Parse<OrderStatus>(dataGridView.SelectedRows[
0].Cells["Status"].Value.ToString()),
Count = Convert.ToInt32(dataGridView.SelectedRows[

View File

@ -38,10 +38,12 @@ namespace ConfectioneryView
services.AddTransient<IComponentStorage, ComponentStorage>();
services.AddTransient<IOrderStorage, OrderStorage>();
services.AddTransient<IPastryStorage, PastryStorage>();
services.AddTransient<IClientStorage, ClientStorage>();
services.AddTransient<IComponentLogic, ComponentLogic>();
services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<IPastryLogic, PastryLogic>();
services.AddTransient<IReportLogic, ReportLogic>();
services.AddTransient<IClientLogic, ClientLogic>();
services.AddTransient<FormMain>();
services.AddTransient<FormComponent>();
services.AddTransient<FormComponents>();
@ -51,6 +53,7 @@ namespace ConfectioneryView
services.AddTransient<FormPastries>();
services.AddTransient<FormReportPastryComponents>();
services.AddTransient<FormReportOrders>();
services.AddTransient<FormClients>();
services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
services.AddTransient<AbstractSaveToWord, SaveToWord>();
services.AddTransient<AbstractSaveToPdf, SaveToPdf>();

View File

@ -6,4 +6,14 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ConfectioneryBusinessLogic\ConfectioneryBusinessLogic.csproj" />
<ProjectReference Include="..\ConfectioneryContracts\ConfectioneryContracts.csproj" />
<ProjectReference Include="..\ConfectioneryDatabaseImplement\ConfectioneryDatabaseImplement.csproj" />
</ItemGroup>
</Project>

View File

@ -1,32 +1,146 @@
using ConfectioneryContracts.BindingModels;
using ConfectioneryContracts.ViewModels;
using ConfectioneryClientApp.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace ConfectioneryClientApp.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<OrderViewModel>>
($"api/main/getorders?clientId={APIClient.Client.Id}"));
}
[HttpGet]
public IActionResult Privacy()
{
return View();
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
return View(APIClient.Client);
}
[HttpPost]
public void Privacy(string login, string password, string fio)
{
if (APIClient.Client == null)
{
throw new Exception(
"Âû êàê ñóäà ïîïàëè? Ñóäà âõîä òîëüêî àâòîðèçîâàííûì");
}
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)
|| string.IsNullOrEmpty(fio))
{
throw new Exception("Ââåäèòå ëîãèí, ïàðîëü è ÔÈÎ");
}
APIClient.PostRequest("api/client/updatedata",
new ClientBindingModel
{
Id = APIClient.Client.Id,
ClientFIO = fio,
Email = login,
Password = password
});
APIClient.Client.ClientFIO = fio;
APIClient.Client.Email = login;
APIClient.Client.Password = password;
Response.Redirect("Index");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None,
NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
return View(new ErrorViewModel
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier
});
}
[HttpGet]
public IActionResult Enter()
{
return View();
}
[HttpPost]
public void Enter(string login, string password)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
{
throw new Exception("Ââåäèòå ëîãèí è ïàðîëü");
}
APIClient.Client = APIClient.GetRequest<ClientViewModel>
($"api/client/login?login={login}&password={password}");
if (APIClient.Client == null)
{
throw new Exception("Íåâåðíûé ëîãèí/ïàðîëü");
}
Response.Redirect("Index");
}
[HttpGet]
public IActionResult Register()
{
return View();
}
[HttpPost]
public void Register(string login, string password, string fio)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)
|| string.IsNullOrEmpty(fio))
{
throw new Exception("Ââåäèòå ëîãèí, ïàðîëü è ÔÈÎ");
}
APIClient.PostRequest("api/client/register", new ClientBindingModel
{
ClientFIO = fio,
Email = login,
Password = password
});
Response.Redirect("Enter");
return;
}
[HttpGet]
public IActionResult Create()
{
ViewBag.Pastries = APIClient.GetRequest<List<PastryViewModel>>
("api/main/getpastrylist");
return View();
}
[HttpPost]
public void Create(int pastry, int count)
{
if (APIClient.Client == null)
{
throw new Exception(
"Âû êàê ñóäà ïîïàëè? Ñóäà âõîä òîëüêî àâòîðèçîâàííûì");
}
if (count <= 0)
{
throw new Exception("Êîëè÷åñòâî è ñóììà äîëæíû áûòü áîëüøå 0");
}
APIClient.PostRequest("api/main/createorder", new OrderBindingModel
{
ClientId = APIClient.Client.Id,
PastryId = pastry,
Count = count,
Sum = Calc(count, pastry)
});
Response.Redirect("Index");
}
[HttpPost]
public double Calc(int count, int pastry)
{
var prod = APIClient.GetRequest<PastryViewModel>
($"api/main/getpastry?pastryId={pastry}");
return count * (prod?.Price ?? 1);
}
}
}

View File

@ -3,7 +3,6 @@ namespace ConfectioneryClientApp.Models
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

View File

@ -1,15 +1,19 @@
using ConfectioneryClientApp;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
APIClient.Connect(builder.Configuration);
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
// The default HSTS value is 30 days. You may want to change
// this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

View File

@ -9,16 +9,7 @@
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5290",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"ConfectioneryClientApp": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,

View File

@ -0,0 +1,56 @@
@{
ViewData["Title"] = "Создание заказа";
}
<div class="text-center">
<h2 class="display-4">Создание заказа</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Кондитерское изделие:</div>
<div class="col-8">
<select id="pastry" name="pastry" class="form-control"
asp-items="@(new SelectList(@ViewBag.Pastries,"Id",
"PastryName"))"></select>
</div>
</div>
<div class="row">
<div class="col-4">Количество:</div>
<div class="col-8">
<input type="text" name="count" id="count" />
</div>
</div>
<div class="row">
<div class="col-4">Сумма:</div>
<div class="col-8">
<input type="text" id="sum" name="sum" readonly />
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4">
<input type="submit" value="Создать" class="btn btn-primary" />
</div>
</div>
</form>
<script>
$('#pastry').on('change', function () {
check();
});
$('#count').on('change', function () {
check();
});
function check() {
var count = $('#count').val();
var pastry = $('#pastry').val();
if (count && pastry) {
$.ajax({
method: "POST",
url: "/Home/Calc",
data: { count: count, pastry: pastry },
success: function (result) {
$("#sum").val(result);
}
});
};
}
</script>

View File

@ -0,0 +1,21 @@
@{
ViewData["Title"] = "Вход в приложение";
}
<div class="text-center">
<h2 class="display-4">Вход в приложение</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Вход"
class="btn btn-primary" /></div>
</div>
</form>

View File

@ -1,8 +1,75 @@
@{
ViewData["Title"] = "Home Page";
@using ConfectioneryContracts.ViewModels
@model List<OrderViewModel>
@{
ViewData["Title"] = "Главная страница";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
<h1 class="display-4">Заказы</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<p>
<a asp-action="Create">Создать заказ</a>
</p>
<table class="table">
<thead>
<tr>
<th>
Номер
</th>
<th>
Кондитерское изделие
</th>
<th>
Дата создания
</th>
<th>
Количество
</th>
<th>
Сумма
</th>
<th>
Статус
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem =>
item.Id)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.PastryName)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.DateCreate)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.Count)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.Sum)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.Status)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -1,6 +1,35 @@
@{
ViewData["Title"] = "Privacy Policy";
@using ConfectioneryContracts.ViewModels
@model ClientViewModel
@{
ViewData["Title"] = "Личные данные";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
<div class="text-center">
<h2 class="display-4">Личные данные</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8">
<input type="text" name="login"
value="@Model.Email" />
</div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8">
<input type="password" name="password" value="@Model.Password" />
</div>
</div>
<div class="row">
<div class="col-4">ФИО:</div>
<div class="col-8">
<input type="text" name="fio" value="@Model.ClientFIO" />
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4">
<input type="submit" value="Сохранить" class="btn btn-primary" />
</div>
</div>
</form>

View File

@ -0,0 +1,26 @@
@{
ViewData["Title"] = "Регистрация";
}
<div class="text-center">
<h2 class="display-4">Регистрация</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" /></div>
</div>
<div class="row">
<div class="col-4">ФИО:</div>
<div class="col-8"><input type="text" name="fio" /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4">
<input type="submit" value="Регистрация" class="btn btn-primary" />
</div>
</div>
</form>

View File

@ -1,6 +1,6 @@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
ViewData["Title"] = "Ошибка";
}
<h1 class="text-danger">Error.</h1>

View File

@ -3,27 +3,34 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - ConfectioneryClientApp</title>
<title>@ViewData["Title"] - Кондитерская</title>
<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="~/ConfectioneryClientApp.styles.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/site.css" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">ConfectioneryClientApp</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bgwhite border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" aspaction="Index">Кондитерская</a>
<button class="navbar-toggler" type="button" datatoggle="collapse" data-target=".navbar-collapse" ariacontrols="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<div class="navbar-collapse collapse d-sm-inline-flex flex-smrow-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Index">Заказы</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Register">Регистрация</a>
</li>
</ul>
</div>
@ -35,15 +42,12 @@
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2024 - ConfectioneryClientApp - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
&copy; 2024 - Кондитерская - <a asp-area="" aspcontroller="Home" asp-action="Privacy">Личные данные</a>
</div>
</footer>
<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>
@await RenderSectionAsync("Scripts", required: false)
@RenderSection("Scripts", required: false)
</body>
</html>

View File

@ -6,5 +6,5 @@
}
},
"AllowedHosts": "*",
"IPAddress": "http://localhost:5159/"
"IPAddress": "http://localhost:5041/"
}

View File

@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace ConfectioneryDatabaseImplement.Migrations
{
[DbContext(typeof(ConfectioneryDatabase))]
[Migration("20240410062130_InitialCreate")]
[Migration("20240508053013_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@ -20,11 +20,36 @@ namespace ConfectioneryDatabaseImplement.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("PastryVersion", "8.0.3")
.HasAnnotation("ProductVersion", "8.0.4")
.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")
@ -53,6 +78,9 @@ namespace ConfectioneryDatabaseImplement.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<int>("Count")
.HasColumnType("int");
@ -73,6 +101,8 @@ namespace ConfectioneryDatabaseImplement.Migrations
b.HasKey("Id");
b.HasIndex("ClientId");
b.HasIndex("PastryId");
b.ToTable("Orders");
@ -126,12 +156,20 @@ namespace ConfectioneryDatabaseImplement.Migrations
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Order", b =>
{
b.HasOne("ConfectioneryDatabaseImplement.Models.Client", "Client")
.WithMany("Orders")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ConfectioneryDatabaseImplement.Models.Pastry", "Pastries")
.WithMany("Orders")
.HasForeignKey("PastryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
b.Navigation("Pastries");
});
@ -154,6 +192,11 @@ namespace ConfectioneryDatabaseImplement.Migrations
b.Navigation("Pastry");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Client", b =>
{
b.Navigation("Orders");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Component", b =>
{
b.Navigation("PastryComponents");

View File

@ -11,6 +11,21 @@ namespace ConfectioneryDatabaseImplement.Migrations
/// <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
@ -50,11 +65,18 @@ namespace ConfectioneryDatabaseImplement.Migrations
Status = table.Column<int>(type: "int", nullable: false),
DateCreate = table.Column<DateTime>(type: "datetime2", nullable: false),
DateImplement = table.Column<DateTime>(type: "datetime2", nullable: true),
PastryId = table.Column<int>(type: "int", nullable: false)
PastryId = table.Column<int>(type: "int", nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
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_Pastries_PastryId",
column: x => x.PastryId,
@ -90,6 +112,11 @@ namespace ConfectioneryDatabaseImplement.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Orders_ClientId",
table: "Orders",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_Orders_PastryId",
table: "Orders",
@ -115,6 +142,9 @@ namespace ConfectioneryDatabaseImplement.Migrations
migrationBuilder.DropTable(
name: "PastryComponents");
migrationBuilder.DropTable(
name: "Clients");
migrationBuilder.DropTable(
name: "Components");

View File

@ -17,11 +17,36 @@ namespace ConfectioneryDatabaseImplement.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("PastryVersion", "8.0.3")
.HasAnnotation("ProductVersion", "8.0.4")
.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")
@ -50,6 +75,9 @@ namespace ConfectioneryDatabaseImplement.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<int>("Count")
.HasColumnType("int");
@ -70,6 +98,8 @@ namespace ConfectioneryDatabaseImplement.Migrations
b.HasKey("Id");
b.HasIndex("ClientId");
b.HasIndex("PastryId");
b.ToTable("Orders");
@ -123,12 +153,20 @@ namespace ConfectioneryDatabaseImplement.Migrations
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Order", b =>
{
b.HasOne("ConfectioneryDatabaseImplement.Models.Client", "Client")
.WithMany("Orders")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ConfectioneryDatabaseImplement.Models.Pastry", "Pastries")
.WithMany("Orders")
.HasForeignKey("PastryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
b.Navigation("Pastries");
});
@ -151,6 +189,11 @@ namespace ConfectioneryDatabaseImplement.Migrations
b.Navigation("Pastry");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Client", b =>
{
b.Navigation("Orders");
});
modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.Component", b =>
{
b.Navigation("PastryComponents");

View File

@ -60,7 +60,7 @@ namespace ConfectioneryDatabaseImplement.Models
DateImplement = DateImplement,
Id = Id,
PastryName = Pastries?.PastryName ?? string.Empty,
ClientFIO = Client?.ClientFIO ?? string.Empty,
ClientFIO = Client?.ClientFIO ?? string.Empty
};
}
}

View File

@ -24,7 +24,8 @@ namespace ConfectioneryFileImplement.Implements
.Where(x => (
(!model.Id.HasValue || x.Id == model.Id) &&
(!model.DateFrom.HasValue || x.DateCreate >= model.DateFrom) &&
(!model.DateTo.HasValue || x.DateCreate <= model.DateTo)
(!model.DateTo.HasValue || x.DateCreate <= model.DateTo) &&
(!model.ClientId.HasValue || x.ClientId == model.ClientId)
)
)
.Select(x => AccessPastryStorage(x.GetViewModel))

View File

@ -56,8 +56,7 @@ namespace ConfectioneryFileImplement.Models
Password = Password
};
public XElement GetXElement => new(
"Client",
public XElement GetXElement => new("Client",
new XAttribute("Id", Id),
new XElement("ClientFIO", ClientFIO),
new XElement("Email", Email.ToString()),

View File

@ -28,7 +28,8 @@ namespace ConfectioneryListImplement.Implements
{
if ((!model.Id.HasValue || order.Id == model.Id) &&
(!model.DateFrom.HasValue || order.DateCreate >= model.DateFrom) &&
(!model.DateTo.HasValue || order.DateCreate <= model.DateTo))
(!model.DateTo.HasValue || order.DateCreate <= model.DateTo) &&
(!model.ClientId.HasValue || order.ClientId == model.ClientId))
{
result.Add(AccessPastryStorage(order.GetViewModel));
}

View File

@ -13,6 +13,7 @@
<ItemGroup>
<ProjectReference Include="..\ConfectioneryBusinessLogic\ConfectioneryBusinessLogic.csproj" />
<ProjectReference Include="..\ConfectioneryContracts\ConfectioneryContracts.csproj" />
<ProjectReference Include="..\ConfectioneryDatabaseImplement\ConfectioneryDatabaseImplement.csproj" />
</ItemGroup>
</Project>

View File

@ -1,6 +0,0 @@
@ConfectioneryRestApi_HostAddress = http://localhost:5041
GET {{ConfectioneryRestApi_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -40,14 +40,13 @@ namespace ConfectioneryRestApi.Controllers
{
return _pastry.ReadElement(new PastrySearchModel
{
Id =
pastryId
Id = pastryId
});
}
catch (Exception ex)
{
_logger.LogError(
ex, "Ошибка получения кондитерского изделия по id={Id}",
ex, "Ошибка получения кондитерского изделия по id = {Id}",
pastryId);
throw;
}
@ -65,7 +64,7 @@ namespace ConfectioneryRestApi.Controllers
catch (Exception ex)
{
_logger.LogError(
ex, "Ошибка получения списка заказов клиента id ={ Id}",
ex, "Ошибка получения списка заказов клиента id = {Id}",
clientId);
throw;
}

View File

@ -3,9 +3,11 @@ using ConfectioneryContracts.BusinessLogicsContracts;
using ConfectioneryContracts.StoragesContracts;
using ConfectioneryDatabaseImplement.Implements;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.SetMinimumLevel(LogLevel.Trace);
builder.Logging.AddLog4Net("log4net.config");
// Add services to the container.
builder.Services.AddTransient<IClientStorage, ClientStorage>();
builder.Services.AddTransient<IOrderStorage, OrderStorage>();
@ -14,8 +16,9 @@ builder.Services.AddTransient<IOrderLogic, OrderLogic>();
builder.Services.AddTransient<IClientLogic, ClientLogic>();
builder.Services.AddTransient<IPastryLogic, PastryLogic>();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at
https://aka.ms/aspnetcore/swashbuckle
// https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
@ -26,6 +29,7 @@ builder.Services.AddSwaggerGen(c =>
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{

View File

@ -9,17 +9,7 @@
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5041",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"ConfectioneryRestApi": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="c:/temp/ComputersShopRestApi.log" />
<file value="c:/temp/ConfectioneryRestApi.log" />
<appendToFile value="true" />
<maximumFileSize value="100KB" />
<maxSizeRollBackups value="2" />