Compare commits

...

9 Commits

Author SHA1 Message Date
Petek1234
421b3d728f Улучшайзинги 2 и 3 2024-12-19 14:22:45 +04:00
Petek1234
d8084733ab Улучшайзинги 1 2024-12-18 15:36:52 +04:00
Petek1234
59aad56527 Лабораторная 3 готовая 2024-12-04 22:00:35 +04:00
Petek1234
b60e109f9d Лаба 3, 2/3 2024-12-04 14:22:33 +04:00
Petek1234
8982751002 Лабораторная 2 готовая 2024-12-01 15:50:35 +04:00
Petek1234
e0fa1ea187 Merge branch 'LabWork_1' into LabWork_2 2024-11-22 10:20:41 +04:00
Petek1234
a5c5a3a234 лаба 1 точно вся готова 2024-11-22 10:14:33 +04:00
Petek1234
d18fe8d659 Лаба 2 не до конца 2024-11-22 08:59:01 +04:00
Petek1234
69e9e6b69e Лаба 1 целиком 2024-11-18 22:27:10 +04:00
83 changed files with 7717 additions and 78 deletions

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities.Enums;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace GasStation.Entities;
public class Cashier
{
public int Id { get; private set; }
[DisplayName("Имя")]
public string FirstName { get; private set; } = string.Empty;
[DisplayName("Фамилия")]
public string LastName { get; private set; } = string.Empty;
public string FullName => $"{LastName} {FirstName}";
[DisplayName("Должность кассира")]
public CashierPost CashierPost { get; private set; }
public static Cashier CreateEntity(int id, string first, string last, CashierPost cashierPost)
{
return new Cashier
{
Id = id,
FirstName = first ?? string.Empty,
LastName = last ?? string.Empty,
CashierPost = cashierPost
};
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GasStation.Entities.Enums;
public enum CashierPost
{
None = 0,
Ordinary = 1,
Senior = 2,
Head = 3
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GasStation.Entities.Enums;
public enum FuelType
{
None,
Fuel_92,
Fuel_95,
Fuel_100,
Fuel_diesel
}

View File

@ -0,0 +1,13 @@
namespace GasStation.Entities.Enums;
[Flags]
public enum SupppliersFuelType
{
None = 0,
Fuel_92 = 1, // 0001
Fuel_95 = 2, // 0010
Fuel_diesel = 4 //
}//

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities.Enums;
namespace GasStation.Entities;
public class Fuel
{
public int Id { get; private set; }
[DisplayName("Цена")]
public int Cost { get; private set; }
[DisplayName("Тип топлива")]
public FuelType Type { get; private set; }
public static Fuel CreateEntity(int id, int cost, FuelType type)
{
return new Fuel
{
Id = id,
Cost = cost,
Type = type
};
}
}

View File

@ -0,0 +1,19 @@
namespace ProjectGasStation.Entities;
public class FuelFuelSale
{
public int Id { get; private set; }
public int FuelId { get; private set; }
public int FuelName { get; private set; }
public int Quantity { get; private set; }
public decimal Price { get; private set; }
public static FuelFuelSale CreateFuelFuelSale(int id, int fuelId, int quantity, decimal price)
{
return new FuelFuelSale { Id = id, FuelId = fuelId, Quantity = quantity, Price = price };
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities.Enums;
using ProjectGasStation.Entities;
namespace GasStation.Entities;
public class FuelSale
{
public int Id { get; private set; }
[Browsable(false)]
public int CashierId { get; private set; }
[DisplayName("Дата продажи")]
public DateTime SaleDate { get; private set; }
[DisplayName("Общая стоимость")]
public decimal TotalPrice { get; private set; }
[DisplayName("Кассир")]
public string CashierName { get; private set; } = string.Empty;
[DisplayName("Топливо")]
public string Fuel => FuelFuelSale != null ?
string.Join(", ", FuelFuelSale.Select(x => $"{(FuelType)x.FuelName} {x.Quantity}")) :
string.Empty;
[Browsable(false)]
public IEnumerable<FuelFuelSale> FuelFuelSale { get; private set; } = [];
public static FuelSale CreateElement(int id, int cashierId, DateTime saleDate, decimal totalPrice, IEnumerable<FuelFuelSale> fuelFuelSale)
{
return new FuelSale
{
Id = id,
CashierId = cashierId,
SaleDate = saleDate,
TotalPrice = totalPrice,
FuelFuelSale = fuelFuelSale
};
}
public void SetFuelFuelSale(IEnumerable<FuelFuelSale> fuelFuelSale)
{
if (fuelFuelSale != null && fuelFuelSale.Any())
{
FuelFuelSale = fuelFuelSale;
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities.Enums;
namespace GasStation.Entities;
public class Supplier
{
public int Id { get; private set; }
[DisplayName("Бренд")]
public string Brand { get; private set; } = string.Empty;
[DisplayName("Поставляемое топливо")]
public SupppliersFuelType Types { get; private set; }
public static Supplier CreateEntity(int id, string brand, SupppliersFuelType types)
{
return new Supplier
{
Id = id,
Brand = brand ?? string.Empty,
Types = types
};
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities.Enums;
using ProjectGasStation.Entities;
namespace GasStation.Entities;
public class SuppliersFuel
{
public int Id { get; private set; }
[Browsable(false)]
public int SuppliersId { get; private set; }
[DisplayName("Бренд поставщика")]
public string SuppliersBrand { get; private set; } = string.Empty;
[DisplayName("Дата поставки")]
public DateTime Date { get; private set; }
[DisplayName("Топливо")]
public string Fuel => SuppliersFuelFuel != null ?
string.Join(", ", SuppliersFuelFuel.Select(x => $"{(FuelType)x.FuelName} {x.Quantity}")) :
string.Empty;
[Browsable(false)]
public IEnumerable<SuppliersFuelFuel> SuppliersFuelFuel { get; private set; } = [];
public static SuppliersFuel CreateElement(int id, int suppliersId, DateTime date, IEnumerable<SuppliersFuelFuel> suppliersFuelFuel)
{
return new SuppliersFuel
{
Id = id,
SuppliersId = suppliersId,
Date = date,
SuppliersFuelFuel = suppliersFuelFuel
};
}
public void SetSuppliersFuelFuel(IEnumerable<SuppliersFuelFuel> suppliersFuelFuel)
{
if (suppliersFuelFuel != null && suppliersFuelFuel.Any())
{
SuppliersFuelFuel = suppliersFuelFuel;
}
}
}

View File

@ -0,0 +1,13 @@
namespace ProjectGasStation.Entities;
public class SuppliersFuelFuel
{
public int Id { get; private set; }
public int FuelId { get; private set; }
public int FuelName { get; private set; }
public int Quantity { get; private set; }
public static SuppliersFuelFuel CreateSuppliersFuelFuel(int id, int fuelId, int quantity)
{
return new SuppliersFuelFuel { Id = id, FuelId = fuelId, Quantity = quantity };
}
}

View File

@ -1,39 +0,0 @@
namespace GasStation
{
partial class Form1
{
/// <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()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Text = "Form1";
}
#endregion
}
}

View File

@ -1,10 +0,0 @@
namespace GasStation
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,168 @@
namespace GasStation
{
partial class FormGasStation
{
/// <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()
{
menuStrip1 = new MenuStrip();
справочникиToolStripMenuItem = new ToolStripMenuItem();
ToolStripMenuItemCashier = new ToolStripMenuItem();
ToolStripMenuItemFuels = new ToolStripMenuItem();
ToolStripMenuItemSuppliers = new ToolStripMenuItem();
операцииToolStripMenuItem = new ToolStripMenuItem();
ToolStripMenuItemFuelSale = new ToolStripMenuItem();
ToolStripMenuItemSuppliersFuel = new ToolStripMenuItem();
отчётыToolStripMenuItem = new ToolStripMenuItem();
DirectoryReportToolStripMenuItem = new ToolStripMenuItem();
FuelReportToolStripMenuItem = new ToolStripMenuItem();
ToolStripFuelDistribution = new ToolStripMenuItem();
menuStrip1.SuspendLayout();
SuspendLayout();
//
// menuStrip1
//
menuStrip1.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, операцииToolStripMenuItem, отчётыToolStripMenuItem });
menuStrip1.Location = new Point(0, 0);
menuStrip1.Name = "menuStrip1";
menuStrip1.Size = new Size(784, 24);
menuStrip1.TabIndex = 0;
menuStrip1.Text = "menuStrip";
//
// справочникиToolStripMenuItem
//
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ToolStripMenuItemCashier, ToolStripMenuItemFuels, ToolStripMenuItemSuppliers });
справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem";
справочникиToolStripMenuItem.Size = new Size(97, 20);
справочникиToolStripMenuItem.Text = "Справочники";
//
// ToolStripMenuItemCashier
//
ToolStripMenuItemCashier.Name = "ToolStripMenuItemCashier";
ToolStripMenuItemCashier.Size = new Size(148, 22);
ToolStripMenuItemCashier.Text = "Кассиры";
ToolStripMenuItemCashier.Click += ToolStripMenuItemCashier_Click;
//
// ToolStripMenuItemFuels
//
ToolStripMenuItemFuels.Name = "ToolStripMenuItemFuels";
ToolStripMenuItemFuels.Size = new Size(148, 22);
ToolStripMenuItemFuels.Text = "Топливо";
ToolStripMenuItemFuels.Click += ToolStripMenuItemFuels_Click;
//
// ToolStripMenuItemSuppliers
//
ToolStripMenuItemSuppliers.Name = "ToolStripMenuItemSuppliers";
ToolStripMenuItemSuppliers.Size = new Size(148, 22);
ToolStripMenuItemSuppliers.Text = "Поставщики";
ToolStripMenuItemSuppliers.Click += ToolStripMenuItemSuppliers_Click;
//
// операцииToolStripMenuItem
//
операцииToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ToolStripMenuItemFuelSale, ToolStripMenuItemSuppliersFuel });
операцииToolStripMenuItem.Name = "операцииToolStripMenuItem";
операцииToolStripMenuItem.Size = new Size(79, 20);
операцииToolStripMenuItem.Text = "Операции";
//
// ToolStripMenuItemFuelSale
//
ToolStripMenuItemFuelSale.Name = "ToolStripMenuItemFuelSale";
ToolStripMenuItemFuelSale.Size = new Size(179, 22);
ToolStripMenuItemFuelSale.Text = "Продажи топлива";
ToolStripMenuItemFuelSale.Click += ToolStripMenuItemFuelSale_Click;
//
// ToolStripMenuItemSuppliersFuel
//
ToolStripMenuItemSuppliersFuel.Name = "ToolStripMenuItemSuppliersFuel";
ToolStripMenuItemSuppliersFuel.Size = new Size(179, 22);
ToolStripMenuItemSuppliersFuel.Text = "Поставки топлива";
ToolStripMenuItemSuppliersFuel.Click += ToolStripMenuItemSuppliersFuel_Click;
//
// отчётыToolStripMenuItem
//
отчётыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { DirectoryReportToolStripMenuItem, FuelReportToolStripMenuItem, ToolStripFuelDistribution });
отчётыToolStripMenuItem.Name = "отчётыToolStripMenuItem";
отчётыToolStripMenuItem.Size = new Size(62, 20);
отчётыToolStripMenuItem.Text = "Отчёты";
//
// DirectoryReportToolStripMenuItem
//
DirectoryReportToolStripMenuItem.Name = "DirectoryReportToolStripMenuItem";
DirectoryReportToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.W;
DirectoryReportToolStripMenuItem.Size = new Size(289, 22);
DirectoryReportToolStripMenuItem.Text = "Документ со справочниками";
DirectoryReportToolStripMenuItem.Click += DirectoryReportToolStripMenuItem_Click;
//
// FuelReportToolStripMenuItem
//
FuelReportToolStripMenuItem.Name = "FuelReportToolStripMenuItem";
FuelReportToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.E;
FuelReportToolStripMenuItem.Size = new Size(289, 22);
FuelReportToolStripMenuItem.Text = "Движение топлива";
FuelReportToolStripMenuItem.Click += FuelReportToolStripMenuItem_Click;
//
// ToolStripFuelDistribution
//
ToolStripFuelDistribution.Name = "ToolStripFuelDistribution";
ToolStripFuelDistribution.ShortcutKeys = Keys.Control | Keys.P;
ToolStripFuelDistribution.Size = new Size(311, 22);
ToolStripFuelDistribution.Text = "Распределение поставок топлива";
ToolStripFuelDistribution.Click += ToolStripFuelDistribution_Click;
//
// FormGasStation
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackgroundImage = Properties.Resources.Заправка;
BackgroundImageLayout = ImageLayout.Stretch;
ClientSize = new Size(784, 411);
Controls.Add(menuStrip1);
MainMenuStrip = menuStrip1;
Name = "FormGasStation";
StartPosition = FormStartPosition.CenterScreen;
Text = "GasStation";
menuStrip1.ResumeLayout(false);
menuStrip1.PerformLayout();
ResumeLayout(false);
PerformLayout();
}
#endregion
private MenuStrip menuStrip1;
private ToolStripMenuItem справочникиToolStripMenuItem;
private ToolStripMenuItem ToolStripMenuItemCashier;
private ToolStripMenuItem операцииToolStripMenuItem;
private ToolStripMenuItem отчётыToolStripMenuItem;
private ToolStripMenuItem ToolStripMenuItemFuels;
private ToolStripMenuItem ToolStripMenuItemSuppliers;
private ToolStripMenuItem ToolStripMenuItemFuelSale;
private ToolStripMenuItem ToolStripMenuItemSuppliersFuel;
private ToolStripMenuItem DirectoryReportToolStripMenuItem;
private ToolStripMenuItem FuelReportToolStripMenuItem;
private ToolStripMenuItem ToolStripFuelDistribution;
}
}

View File

@ -0,0 +1,119 @@
using GasStation.Forms;
using Unity;
namespace GasStation;
public partial class FormGasStation : Form
{
private readonly IUnityContainer _container;
public FormGasStation(IUnityContainer container)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
}
private void ToolStripMenuItemCashier_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormCashiers>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ToolStripMenuItemFuels_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormFuels>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ToolStripMenuItemSuppliers_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormSuppliers>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ToolStripMenuItemFuelSale_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormFuelSales>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ToolStripMenuItemSuppliersFuel_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormSupplierFuels>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DirectoryReportToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormDirectoryReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FuelReportToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormFuelReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ToolStripFuelDistribution_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormSuppliersFuelDistributionReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

View File

@ -0,0 +1,123 @@
<?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>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,142 @@
namespace GasStation.Forms
{
partial class FormCashier
{
/// <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()
{
comboBoxPost = new ComboBox();
textBoxFirstName = new TextBox();
textBoxLastName = new TextBox();
ButtonSave = new Button();
ButtonCancel = new Button();
label1 = new Label();
label2 = new Label();
label3 = new Label();
SuspendLayout();
//
// comboBoxPost
//
comboBoxPost.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoxPost.FormattingEnabled = true;
comboBoxPost.Location = new Point(159, 107);
comboBoxPost.Name = "comboBoxPost";
comboBoxPost.Size = new Size(145, 23);
comboBoxPost.TabIndex = 0;
//
// textBoxFirstName
//
textBoxFirstName.Location = new Point(159, 23);
textBoxFirstName.Name = "textBoxFirstName";
textBoxFirstName.Size = new Size(145, 23);
textBoxFirstName.TabIndex = 1;
//
// textBoxLastName
//
textBoxLastName.Location = new Point(159, 64);
textBoxLastName.Name = "textBoxLastName";
textBoxLastName.Size = new Size(145, 23);
textBoxLastName.TabIndex = 2;
//
// ButtonSave
//
ButtonSave.Location = new Point(69, 168);
ButtonSave.Name = "ButtonSave";
ButtonSave.Size = new Size(87, 25);
ButtonSave.TabIndex = 3;
ButtonSave.Text = "Сохранить";
ButtonSave.UseVisualStyleBackColor = true;
ButtonSave.Click += ButtonSave_Click;
//
// ButtonCancel
//
ButtonCancel.Location = new Point(185, 168);
ButtonCancel.Name = "ButtonCancel";
ButtonCancel.Size = new Size(96, 25);
ButtonCancel.TabIndex = 4;
ButtonCancel.Text = "Отмена";
ButtonCancel.UseVisualStyleBackColor = true;
ButtonCancel.Click += ButtonCancel_Click;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(29, 26);
label1.Name = "label1";
label1.Size = new Size(35, 15);
label1.TabIndex = 5;
label1.Text = "Имя:";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(29, 67);
label2.Name = "label2";
label2.Size = new Size(65, 15);
label2.TabIndex = 6;
label2.Text = "Фамилия:";
//
// label3
//
label3.AutoSize = true;
label3.Location = new Point(29, 110);
label3.Name = "label3";
label3.Size = new Size(75, 15);
label3.TabIndex = 7;
label3.Text = "Должность:";
//
// FormCashier
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(340, 212);
Controls.Add(label3);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(ButtonCancel);
Controls.Add(ButtonSave);
Controls.Add(textBoxLastName);
Controls.Add(textBoxFirstName);
Controls.Add(comboBoxPost);
Name = "FormCashier";
StartPosition = FormStartPosition.CenterParent;
Text = "Кассир";
ResumeLayout(false);
PerformLayout();
}
#endregion
private ComboBox comboBoxPost;
private TextBox textBoxFirstName;
private TextBox textBoxLastName;
private Button ButtonSave;
private Button ButtonCancel;
private Label label1;
private Label label2;
private Label label3;
}
}

View File

@ -0,0 +1,84 @@
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 GasStation.Entities;
using GasStation.Entities.Enums;
using GasStation.Repositories;
using GasStation.Repositories.Implementations;
namespace GasStation.Forms;
public partial class FormCashier : Form
{
public readonly ICashierRepository _cashierRepository;
private int? _cashierId;
public int Id
{
set
{
try
{
var cashier = _cashierRepository.ReadCashierById(value);
if (cashier == null)
{
throw new InvalidDataException(nameof(cashier));
}
textBoxFirstName.Text = cashier.FirstName;
textBoxLastName.Text = cashier.LastName;
comboBoxPost.SelectedItem = cashier.CashierPost;
_cashierId = cashier.Id;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при получении данных", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
}
public FormCashier(ICashierRepository cashierRepository)
{
InitializeComponent();
_cashierRepository = cashierRepository ?? throw new ArgumentNullException(nameof(cashierRepository));
comboBoxPost.DataSource = Enum.GetValues(typeof(CashierPost));
}
private void ButtonSave_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(textBoxFirstName.Text) || string.IsNullOrWhiteSpace(textBoxLastName.Text))
{
throw new Exception("Имеются незаполненные поля");
}
if (_cashierId.HasValue)
{
_cashierRepository.UpdateCashier(CreateCashier(_cashierId.Value));
}
else
{
_cashierRepository.CreateCashier(CreateCashier(0));
}
Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при сохранении",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
private Cashier CreateCashier(int id) => Cashier.CreateEntity(id, textBoxFirstName.Text, textBoxLastName.Text,(CashierPost)comboBoxPost.SelectedItem!);
}

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
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
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>
@ -26,36 +26,36 @@
<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
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
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
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
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
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
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
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->

View File

@ -0,0 +1,128 @@
namespace GasStation.Forms
{
partial class FormCashiers
{
/// <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()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormCashiers));
panel1 = new Panel();
ButtonDel = new Button();
ButtonUpd = new Button();
ButtonAdd = new Button();
dataGridView = new DataGridView();
panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// panel1
//
panel1.Controls.Add(ButtonDel);
panel1.Controls.Add(ButtonUpd);
panel1.Controls.Add(ButtonAdd);
panel1.Dock = DockStyle.Right;
panel1.Location = new Point(623, 0);
panel1.Name = "panel1";
panel1.Size = new Size(114, 413);
panel1.TabIndex = 0;
//
// ButtonDel
//
ButtonDel.BackgroundImage = Properties.Resources.Минус;
ButtonDel.BackgroundImageLayout = ImageLayout.Stretch;
ButtonDel.Location = new Point(18, 184);
ButtonDel.Name = "ButtonDel";
ButtonDel.Size = new Size(80, 80);
ButtonDel.TabIndex = 2;
ButtonDel.UseVisualStyleBackColor = true;
ButtonDel.Click += ButtonDel_Click;
//
// ButtonUpd
//
ButtonUpd.BackgroundImage = (Image)resources.GetObject("ButtonUpd.BackgroundImage");
ButtonUpd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonUpd.Location = new Point(18, 98);
ButtonUpd.Name = "ButtonUpd";
ButtonUpd.Size = new Size(80, 80);
ButtonUpd.TabIndex = 1;
ButtonUpd.UseVisualStyleBackColor = true;
ButtonUpd.Click += ButtonUpd_Click;
//
// ButtonAdd
//
ButtonAdd.BackgroundImage = Properties.Resources.Плюс;
ButtonAdd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonAdd.Location = new Point(18, 12);
ButtonAdd.Name = "ButtonAdd";
ButtonAdd.Size = new Size(80, 80);
ButtonAdd.TabIndex = 0;
ButtonAdd.UseVisualStyleBackColor = true;
ButtonAdd.Click += ButtonAdd_Click;
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToResizeColumns = false;
dataGridView.AllowUserToResizeRows = false;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(0, 0);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersVisible = false;
dataGridView.RowTemplate.Height = 25;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(623, 413);
dataGridView.TabIndex = 1;
//
// FormCashiers
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(737, 413);
Controls.Add(dataGridView);
Controls.Add(panel1);
Name = "FormCashiers";
StartPosition = FormStartPosition.CenterParent;
Text = "Кассиры";
Load += FormCashiers_Load;
panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private Panel panel1;
private Button ButtonDel;
private Button ButtonUpd;
private Button ButtonAdd;
private DataGridView dataGridView;
}
}

View File

@ -0,0 +1,116 @@
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 System.Xml.Linq;
using GasStation.Repositories;
using Unity;
namespace GasStation.Forms;
public partial class FormCashiers : Form
{
private readonly IUnityContainer _container;
private readonly ICashierRepository _cashierRepository;
public FormCashiers(IUnityContainer container, ICashierRepository cashierRepository)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
_cashierRepository = cashierRepository ?? throw new ArgumentNullException(nameof(cashierRepository));
}
private void FormCashiers_Load(object sender, EventArgs e)
{
try
{
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormCashier>().ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при добавлении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonUpd_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
try
{
var form = _container.Resolve<FormCashier>();
form.Id = findId;
form.ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при изменении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonDel_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
if (MessageBox.Show("Удалить запись?", "Удаление", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return;
}
try
{
_cashierRepository.DeleteCashier(findId);
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при удалении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList()
{
dataGridView.DataSource = _cashierRepository.ReadCashiers();
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["FullName"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
id = 0;
if (dataGridView.SelectedRows.Count < 1)
{
MessageBox.Show("Нет выбранной записи", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
return true;
}
}

View File

@ -0,0 +1,197 @@
<?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>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ButtonUpd.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
oUIOarX/AceT4DvUQEgWAAAAAElFTkSuQmCC
</value>
</data>
</root>

View File

@ -0,0 +1,100 @@
namespace GasStation.Forms
{
partial class FormDirectoryReport
{
/// <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()
{
checkBoxFuel = new CheckBox();
checkBoxCashier = new CheckBox();
checkBoxSupplier = new CheckBox();
ButtonBuild = new Button();
SuspendLayout();
//
// checkBoxFuel
//
checkBoxFuel.AutoSize = true;
checkBoxFuel.Location = new Point(26, 12);
checkBoxFuel.Name = "checkBoxFuel";
checkBoxFuel.Size = new Size(75, 19);
checkBoxFuel.TabIndex = 0;
checkBoxFuel.Text = "Топливо";
checkBoxFuel.UseVisualStyleBackColor = true;
//
// checkBoxCashier
//
checkBoxCashier.AutoSize = true;
checkBoxCashier.Location = new Point(26, 56);
checkBoxCashier.Name = "checkBoxCashier";
checkBoxCashier.Size = new Size(77, 19);
checkBoxCashier.TabIndex = 1;
checkBoxCashier.Text = "Кассиры";
checkBoxCashier.UseVisualStyleBackColor = true;
//
// checkBoxSupplier
//
checkBoxSupplier.AutoSize = true;
checkBoxSupplier.Location = new Point(26, 100);
checkBoxSupplier.Name = "checkBoxSupplier";
checkBoxSupplier.Size = new Size(100, 19);
checkBoxSupplier.TabIndex = 2;
checkBoxSupplier.Text = "Поставщики";
checkBoxSupplier.UseVisualStyleBackColor = true;
//
// ButtonBuild
//
ButtonBuild.Location = new Point(174, 49);
ButtonBuild.Name = "ButtonBuild";
ButtonBuild.Size = new Size(102, 30);
ButtonBuild.TabIndex = 3;
ButtonBuild.Text = "Сформировать";
ButtonBuild.UseVisualStyleBackColor = true;
ButtonBuild.Click += ButtonBuild_Click;
//
// FormDirectoryReport
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(297, 133);
Controls.Add(ButtonBuild);
Controls.Add(checkBoxSupplier);
Controls.Add(checkBoxCashier);
Controls.Add(checkBoxFuel);
Name = "FormDirectoryReport";
StartPosition = FormStartPosition.CenterParent;
Text = "FormDirectoryReport";
ResumeLayout(false);
PerformLayout();
}
#endregion
private CheckBox checkBoxFuel;
private CheckBox checkBoxCashier;
private CheckBox checkBoxSupplier;
private Button ButtonBuild;
}
}

View File

@ -0,0 +1,61 @@
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 GasStation.Reports;
using Unity;
namespace GasStation.Forms;
public partial class FormDirectoryReport : Form
{
private readonly IUnityContainer _container;
public FormDirectoryReport(IUnityContainer container)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
}
private void ButtonBuild_Click(object sender, EventArgs e)
{
try
{
if (!checkBoxFuel.Checked && !checkBoxCashier.Checked && !checkBoxSupplier.Checked)
{
throw new Exception("Не выбран ни один справочник для выгрузки");
}
var sfd = new SaveFileDialog()
{
Filter = "Docx Files | *.docx"
};
if (sfd.ShowDialog() != DialogResult.OK)
{
throw new Exception("Не выбран файла для отчета");
}
if (_container.Resolve<DocReport>().CreateDoc(sfd.FileName, checkBoxFuel.Checked,
checkBoxCashier.Checked, checkBoxSupplier.Checked))
{
MessageBox.Show("Документ сформирован", "Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Возникли ошибки при формировании документа.Подробности в логах",
"Формирование документа", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception 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

@ -0,0 +1,121 @@
namespace GasStation.Forms
{
partial class FormFuel
{
/// <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()
{
numericUpDownCost = new NumericUpDown();
comboBoxType = new ComboBox();
ButtonSave = new Button();
ButtonCancel = new Button();
label1 = new Label();
label2 = new Label();
((System.ComponentModel.ISupportInitialize)numericUpDownCost).BeginInit();
SuspendLayout();
//
// numericUpDownCost
//
numericUpDownCost.Location = new Point(113, 19);
numericUpDownCost.Name = "numericUpDownCost";
numericUpDownCost.Size = new Size(158, 23);
numericUpDownCost.TabIndex = 0;
//
// comboBoxType
//
comboBoxType.FormattingEnabled = true;
comboBoxType.Location = new Point(113, 64);
comboBoxType.Name = "comboBoxType";
comboBoxType.Size = new Size(158, 23);
comboBoxType.TabIndex = 1;
//
// ButtonSave
//
ButtonSave.Location = new Point(37, 107);
ButtonSave.Name = "ButtonSave";
ButtonSave.Size = new Size(96, 25);
ButtonSave.TabIndex = 2;
ButtonSave.Text = "Сохранить";
ButtonSave.UseVisualStyleBackColor = true;
ButtonSave.Click += ButtonSave_Click;
//
// ButtonCancel
//
ButtonCancel.Location = new Point(148, 107);
ButtonCancel.Name = "ButtonCancel";
ButtonCancel.Size = new Size(96, 25);
ButtonCancel.TabIndex = 3;
ButtonCancel.Text = "Отмена";
ButtonCancel.UseVisualStyleBackColor = true;
ButtonCancel.Click += ButtonCancel_Click;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(12, 23);
label1.Name = "label1";
label1.Size = new Size(40, 15);
label1.TabIndex = 4;
label1.Text = "Цена:";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(12, 67);
label2.Name = "label2";
label2.Size = new Size(83, 15);
label2.TabIndex = 5;
label2.Text = "Вид топлива:";
//
// FormFuel
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(286, 148);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(ButtonCancel);
Controls.Add(ButtonSave);
Controls.Add(comboBoxType);
Controls.Add(numericUpDownCost);
Name = "FormFuel";
StartPosition = FormStartPosition.CenterParent;
Text = "Топливо";
((System.ComponentModel.ISupportInitialize)numericUpDownCost).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private NumericUpDown numericUpDownCost;
private ComboBox comboBoxType;
private Button ButtonSave;
private Button ButtonCancel;
private Label label1;
private Label label2;
}
}

View File

@ -0,0 +1,82 @@
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 GasStation.Entities;
using GasStation.Entities.Enums;
using GasStation.Repositories;
using GasStation.Repositories.Implementations;
namespace GasStation.Forms;
public partial class FormFuel : Form
{
private readonly IFuelRepository _fuelRepository;
private int? _fuelId;
public int Id
{
set
{
try
{
var fuel = _fuelRepository.ReadFuelById(value);
if (fuel == null)
{
throw new InvalidDataException(nameof(fuel));
}
numericUpDownCost.Value = (decimal)fuel.Cost;
comboBoxType.SelectedItem = fuel.Type;
_fuelId = fuel.Id;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при получении данных", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
}
public FormFuel(IFuelRepository fuelRepository)
{
InitializeComponent();
_fuelRepository = fuelRepository ?? throw new ArgumentNullException(nameof(fuelRepository));
comboBoxType.DataSource = Enum.GetValues(typeof(FuelType));
}
private void ButtonSave_Click(object sender, EventArgs e)
{
try
{
if (numericUpDownCost.Value == 0 || comboBoxType.SelectedIndex < 1)
{
throw new Exception("Имеются незаполненные поля");
}
if (_fuelId.HasValue)
{
_fuelRepository.UpdateFuel(CreateFuel(_fuelId.Value));
}
else
{
_fuelRepository.CreateFuel(CreateFuel(0));
}
Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при сохранении",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
private Fuel CreateFuel(int id) => Fuel.CreateEntity(id, (int)numericUpDownCost.Value, (FuelType)comboBoxType.SelectedItem!);
}

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

@ -0,0 +1,165 @@
namespace GasStation.Forms
{
partial class FormFuelReport
{
/// <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()
{
dateTimePickerStart = new DateTimePicker();
label1 = new Label();
label2 = new Label();
label3 = new Label();
label4 = new Label();
dateTimePickerEnd = new DateTimePicker();
comboBoxFuel = new ComboBox();
textBoxFilePath = new TextBox();
ButtonFile = new Button();
ButtonBuild = new Button();
SuspendLayout();
//
// dateTimePickerStart
//
dateTimePickerStart.Location = new Point(120, 112);
dateTimePickerStart.Name = "dateTimePickerStart";
dateTimePickerStart.Size = new Size(200, 23);
dateTimePickerStart.TabIndex = 0;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(12, 28);
label1.Name = "label1";
label1.Size = new Size(93, 15);
label1.TabIndex = 1;
label1.Text = "Путь до файла:";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(12, 72);
label2.Name = "label2";
label2.Size = new Size(59, 15);
label2.TabIndex = 2;
label2.Text = "Топливо:";
//
// label3
//
label3.AutoSize = true;
label3.Location = new Point(12, 116);
label3.Name = "label3";
label3.Size = new Size(78, 15);
label3.TabIndex = 3;
label3.Text = "Дата начала:";
//
// label4
//
label4.AutoSize = true;
label4.Location = new Point(12, 162);
label4.Name = "label4";
label4.Size = new Size(74, 15);
label4.TabIndex = 4;
label4.Text = "Дата конца:";
//
// dateTimePickerEnd
//
dateTimePickerEnd.Location = new Point(120, 158);
dateTimePickerEnd.Name = "dateTimePickerEnd";
dateTimePickerEnd.Size = new Size(200, 23);
dateTimePickerEnd.TabIndex = 5;
//
// comboBoxFuel
//
comboBoxFuel.FormattingEnabled = true;
comboBoxFuel.Location = new Point(120, 67);
comboBoxFuel.Name = "comboBoxFuel";
comboBoxFuel.Size = new Size(200, 23);
comboBoxFuel.TabIndex = 6;
//
// textBoxFilePath
//
textBoxFilePath.Location = new Point(120, 25);
textBoxFilePath.Name = "textBoxFilePath";
textBoxFilePath.ReadOnly = true;
textBoxFilePath.Size = new Size(164, 23);
textBoxFilePath.TabIndex = 7;
//
// ButtonFile
//
ButtonFile.Location = new Point(290, 25);
ButtonFile.Name = "ButtonFile";
ButtonFile.Size = new Size(32, 25);
ButtonFile.TabIndex = 8;
ButtonFile.Text = "...";
ButtonFile.UseVisualStyleBackColor = true;
ButtonFile.Click += ButtonFile_Click;
//
// ButtonBuild
//
ButtonBuild.Location = new Point(12, 192);
ButtonBuild.Name = "ButtonBuild";
ButtonBuild.Size = new Size(308, 27);
ButtonBuild.TabIndex = 9;
ButtonBuild.Text = "Сформировать";
ButtonBuild.UseVisualStyleBackColor = true;
ButtonBuild.Click += ButtonBuild_Click;
//
// FormFuelReport
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(332, 228);
Controls.Add(ButtonBuild);
Controls.Add(ButtonFile);
Controls.Add(textBoxFilePath);
Controls.Add(comboBoxFuel);
Controls.Add(dateTimePickerEnd);
Controls.Add(label4);
Controls.Add(label3);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(dateTimePickerStart);
Name = "FormFuelReport";
StartPosition = FormStartPosition.CenterParent;
Text = "FormFuelReport";
ResumeLayout(false);
PerformLayout();
}
#endregion
private DateTimePicker dateTimePickerStart;
private Label label1;
private Label label2;
private Label label3;
private Label label4;
private DateTimePicker dateTimePickerEnd;
private ComboBox comboBoxFuel;
private TextBox textBoxFilePath;
private Button button;
private Button ButtonFile;
private Button ButtonBuild;
}
}

View File

@ -0,0 +1,77 @@
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 GasStation.Reports;
using GasStation.Repositories;
using Unity;
namespace GasStation.Forms
{
public partial class FormFuelReport : Form
{
private readonly IUnityContainer _container;
public FormFuelReport(IUnityContainer container, IFuelRepository fuelRepository)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
comboBoxFuel.DataSource = fuelRepository.ReadFuels();
comboBoxFuel.DisplayMember = "Type";
comboBoxFuel.ValueMember = "Id";
}
private void ButtonFile_Click(object sender, EventArgs e)
{
var sfd = new SaveFileDialog()
{
Filter = "Excel Files | *.xlsx"
};
if (sfd.ShowDialog() != DialogResult.OK)
{
return;
}
textBoxFilePath.Text = sfd.FileName;
}
private void ButtonBuild_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(textBoxFilePath.Text))
{
throw new Exception("Отсутствует имя файла для отчета");
}
if (comboBoxFuel.SelectedIndex < 0)
{
throw new Exception("Не выбран корм");
}
if (dateTimePickerEnd.Value <= dateTimePickerStart.Value)
{
throw new Exception("Дата начала должна быть раньше даты окончания");
}
if (_container.Resolve<TableReport>().CreateTable(textBoxFilePath.Text, (int)comboBoxFuel.SelectedValue!, dateTimePickerStart.Value, dateTimePickerEnd.Value))
{
MessageBox.Show("Документ сформирован", "Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Возникли ошибки при формировании документа.Подробности в логах",
"Формирование документа", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception 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

@ -0,0 +1,171 @@
namespace GasStation.Forms
{
partial class FormFuelSale
{
/// <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()
{
comboBoxCashier = new ComboBox();
dateTimePickerDate = new DateTimePicker();
groupBox1 = new GroupBox();
dataGridView = new DataGridView();
ColumnFuel = new DataGridViewComboBoxColumn();
ColumnQuantity = new DataGridViewTextBoxColumn();
label1 = new Label();
label2 = new Label();
ButtonSave = new Button();
ButtonCancel = new Button();
groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// comboBoxCashier
//
comboBoxCashier.FormattingEnabled = true;
comboBoxCashier.Location = new Point(105, 12);
comboBoxCashier.Name = "comboBoxCashier";
comboBoxCashier.Size = new Size(173, 23);
comboBoxCashier.TabIndex = 0;
//
// dateTimePickerDate
//
dateTimePickerDate.Location = new Point(105, 58);
dateTimePickerDate.Name = "dateTimePickerDate";
dateTimePickerDate.Size = new Size(173, 23);
dateTimePickerDate.TabIndex = 1;
//
// groupBox1
//
groupBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
groupBox1.Controls.Add(dataGridView);
groupBox1.Location = new Point(12, 101);
groupBox1.Name = "groupBox1";
groupBox1.Size = new Size(270, 245);
groupBox1.TabIndex = 2;
groupBox1.TabStop = false;
groupBox1.Text = "Топливо";
//
// dataGridView
//
dataGridView.AllowUserToResizeColumns = false;
dataGridView.AllowUserToResizeRows = false;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Columns.AddRange(new DataGridViewColumn[] { ColumnFuel, ColumnQuantity });
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(3, 19);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.RowHeadersVisible = false;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(264, 223);
dataGridView.TabIndex = 0;
//
// ColumnFuel
//
ColumnFuel.HeaderText = "Топливо";
ColumnFuel.Name = "ColumnFuel";
//
// ColumnQuantity
//
ColumnQuantity.HeaderText = "Количество";
ColumnQuantity.Name = "ColumnQuantity";
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(3, 17);
label1.Name = "label1";
label1.Size = new Size(68, 15);
label1.TabIndex = 3;
label1.Text = "Продавец:";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(3, 64);
label2.Name = "label2";
label2.Size = new Size(91, 15);
label2.TabIndex = 4;
label2.Text = "Дата продажи:";
//
// ButtonSave
//
ButtonSave.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
ButtonSave.Location = new Point(15, 358);
ButtonSave.Name = "ButtonSave";
ButtonSave.Size = new Size(118, 31);
ButtonSave.TabIndex = 5;
ButtonSave.Text = "Сохранить";
ButtonSave.UseVisualStyleBackColor = true;
ButtonSave.Click += ButtonSave_Click;
//
// ButtonCancel
//
ButtonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
ButtonCancel.Location = new Point(162, 358);
ButtonCancel.Name = "ButtonCancel";
ButtonCancel.Size = new Size(118, 31);
ButtonCancel.TabIndex = 6;
ButtonCancel.Text = "Отмена";
ButtonCancel.UseVisualStyleBackColor = true;
ButtonCancel.Click += ButtonCancel_Click;
//
// FormFuelSale
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(292, 401);
Controls.Add(ButtonCancel);
Controls.Add(ButtonSave);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(groupBox1);
Controls.Add(dateTimePickerDate);
Controls.Add(comboBoxCashier);
Name = "FormFuelSale";
StartPosition = FormStartPosition.CenterParent;
Text = "FormFuelSale";
groupBox1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private ComboBox comboBoxCashier;
private DateTimePicker dateTimePickerDate;
private GroupBox groupBox1;
private Label label1;
private Label label2;
private DataGridView dataGridView;
private Button ButtonSave;
private Button ButtonCancel;
private DataGridViewComboBoxColumn ColumnFuel;
private DataGridViewTextBoxColumn ColumnQuantity;
}
}

View File

@ -0,0 +1,74 @@
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 GasStation.Entities;
using GasStation.Repositories;
using ProjectGasStation.Entities;
namespace GasStation.Forms;
public partial class FormFuelSale : Form
{
private readonly IFuelSalesRepository _fuelSalesRepository;
public FormFuelSale(IFuelSalesRepository fuelSalesRepository,
ICashierRepository cashierRepository,
IFuelRepository fuelRepository)
{
InitializeComponent();
_fuelSalesRepository = fuelSalesRepository ?? throw new ArgumentNullException(nameof(fuelSalesRepository));
comboBoxCashier.DataSource = cashierRepository.ReadCashiers();
comboBoxCashier.DisplayMember = "FullName";
comboBoxCashier.ValueMember = "Id";
ColumnFuel.DataSource = fuelRepository.ReadFuels();
ColumnFuel.DisplayMember = "Type";
ColumnFuel.ValueMember = "Id";
}
private void ButtonSave_Click(object sender, EventArgs e)
{
try
{
if (dataGridView.RowCount < 1 || comboBoxCashier.SelectedIndex < 0)
{
throw new Exception("Имеются незаполненные поля");
}
int countQuantity = int.Parse(dataGridView.Rows[0].Cells["ColumnQuantity"].Value?.ToString() ?? "0");
_fuelSalesRepository.CreateFuelSale(FuelSale.CreateElement(0,
(int)comboBoxCashier.SelectedValue!, dateTimePickerDate.Value, countQuantity, CreateListFuelFuelSaleFromDataGrid()));
Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при сохранении",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
private List<FuelFuelSale> CreateListFuelFuelSaleFromDataGrid()
{
var list = new List<FuelFuelSale>();
foreach (DataGridViewRow row in dataGridView.Rows)
{
if (row.Cells["ColumnFuel"].Value == null || row.Cells["ColumnQuantity"].Value == null)
{
continue;
}
list.Add(FuelFuelSale.CreateFuelFuelSale(0,
Convert.ToInt32(row.Cells["ColumnFuel"].Value),
Convert.ToInt32(row.Cells["ColumnQuantity"].Value), 0));
}
return list.GroupBy(x => x.FuelId, x => x.Quantity, (id, counts) =>
FuelFuelSale.CreateFuelFuelSale(0, id, counts.Sum(), 0)).ToList();
}
}

View File

@ -0,0 +1,126 @@
<?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>
<metadata name="ColumnFuel.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnQuantity.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@ -0,0 +1,113 @@
namespace GasStation.Forms
{
partial class FormFuelSales
{
/// <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()
{
panel1 = new Panel();
ButtonDel = new Button();
ButtonAdd = new Button();
dataGridViewData = new DataGridView();
panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridViewData).BeginInit();
SuspendLayout();
//
// panel1
//
panel1.Controls.Add(ButtonDel);
panel1.Controls.Add(ButtonAdd);
panel1.Dock = DockStyle.Right;
panel1.Location = new Point(623, 0);
panel1.Name = "panel1";
panel1.Size = new Size(114, 413);
panel1.TabIndex = 0;
//
// ButtonDel
//
ButtonDel.BackgroundImage = Properties.Resources.Минус;
ButtonDel.BackgroundImageLayout = ImageLayout.Stretch;
ButtonDel.Location = new Point(22, 98);
ButtonDel.Name = "ButtonDel";
ButtonDel.Size = new Size(80, 80);
ButtonDel.TabIndex = 1;
ButtonDel.UseVisualStyleBackColor = true;
ButtonDel.Click += ButtonDel_Click;
//
// ButtonAdd
//
ButtonAdd.BackgroundImage = Properties.Resources.Плюс;
ButtonAdd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonAdd.Location = new Point(22, 12);
ButtonAdd.Name = "ButtonAdd";
ButtonAdd.Size = new Size(80, 80);
ButtonAdd.TabIndex = 0;
ButtonAdd.UseVisualStyleBackColor = true;
ButtonAdd.Click += ButtonAdd_Click;
//
// dataGridViewData
//
dataGridViewData.AllowUserToAddRows = false;
dataGridViewData.AllowUserToDeleteRows = false;
dataGridViewData.AllowUserToResizeColumns = false;
dataGridViewData.AllowUserToResizeRows = false;
dataGridViewData.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridViewData.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridViewData.Dock = DockStyle.Fill;
dataGridViewData.Location = new Point(0, 0);
dataGridViewData.MultiSelect = false;
dataGridViewData.Name = "dataGridViewData";
dataGridViewData.ReadOnly = true;
dataGridViewData.RowHeadersVisible = false;
dataGridViewData.RowTemplate.Height = 25;
dataGridViewData.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridViewData.Size = new Size(623, 413);
dataGridViewData.TabIndex = 1;
//
// FormFuelSales
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(737, 413);
Controls.Add(dataGridViewData);
Controls.Add(panel1);
Name = "FormFuelSales";
StartPosition = FormStartPosition.CenterParent;
Text = "Продажи";
Load += FormFuels_Load;
panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridViewData).EndInit();
ResumeLayout(false);
}
#endregion
private Panel panel1;
private Button ButtonDel;
private Button ButtonAdd;
private DataGridView dataGridViewData;
}
}

View File

@ -0,0 +1,95 @@
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 GasStation.Repositories;
using GasStation.Repositories.Implementations;
using Unity;
namespace GasStation.Forms;
public partial class FormFuelSales : Form
{
private readonly IUnityContainer _container;
private readonly IFuelSalesRepository _fuelSalesRepository;
public FormFuelSales(IUnityContainer container, IFuelSalesRepository fuelSalesRepository)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
_fuelSalesRepository = fuelSalesRepository ?? throw new ArgumentNullException(nameof(fuelSalesRepository));
}
private void FormFuels_Load(object sender, EventArgs e)
{
try
{
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormFuelSale>().ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при добавлении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonDel_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
if (MessageBox.Show("Удалить запись?", "Удаление", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return;
}
try
{
_fuelSalesRepository.DeleteFuelSale(findId);
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при удалении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList()
{
dataGridViewData.DataSource = _fuelSalesRepository.ReadFuelSale();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["SaleDate"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm";
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
id = 0;
if (dataGridViewData.SelectedRows.Count < 1)
{
MessageBox.Show("Нет выбранной записи", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
id = Convert.ToInt32(dataGridViewData.SelectedRows[0].Cells["Id"].Value);
return true;
}
}

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

@ -0,0 +1,128 @@
namespace GasStation.Forms
{
partial class FormFuels
{
/// <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()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormFuels));
panel1 = new Panel();
ButtonDel = new Button();
ButtonUpd = new Button();
ButtonAdd = new Button();
dataGridView = new DataGridView();
panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// panel1
//
panel1.Controls.Add(ButtonDel);
panel1.Controls.Add(ButtonUpd);
panel1.Controls.Add(ButtonAdd);
panel1.Dock = DockStyle.Right;
panel1.Location = new Point(623, 0);
panel1.Name = "panel1";
panel1.Size = new Size(114, 413);
panel1.TabIndex = 0;
//
// ButtonDel
//
ButtonDel.BackgroundImage = Properties.Resources.Минус;
ButtonDel.BackgroundImageLayout = ImageLayout.Stretch;
ButtonDel.Location = new Point(21, 184);
ButtonDel.Name = "ButtonDel";
ButtonDel.Size = new Size(80, 80);
ButtonDel.TabIndex = 2;
ButtonDel.UseVisualStyleBackColor = true;
ButtonDel.Click += ButtonDel_Click;
//
// ButtonUpd
//
ButtonUpd.BackgroundImage = (Image)resources.GetObject("ButtonUpd.BackgroundImage");
ButtonUpd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonUpd.Location = new Point(21, 98);
ButtonUpd.Name = "ButtonUpd";
ButtonUpd.Size = new Size(80, 80);
ButtonUpd.TabIndex = 1;
ButtonUpd.UseVisualStyleBackColor = true;
ButtonUpd.Click += ButtonUpd_Click;
//
// ButtonAdd
//
ButtonAdd.BackgroundImage = Properties.Resources.Плюс;
ButtonAdd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonAdd.Location = new Point(21, 12);
ButtonAdd.Name = "ButtonAdd";
ButtonAdd.Size = new Size(80, 80);
ButtonAdd.TabIndex = 0;
ButtonAdd.UseVisualStyleBackColor = true;
ButtonAdd.Click += ButtonAdd_Click;
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToResizeColumns = false;
dataGridView.AllowUserToResizeRows = false;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(0, 0);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersVisible = false;
dataGridView.RowTemplate.Height = 25;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(623, 413);
dataGridView.TabIndex = 1;
//
// FormFuels
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(737, 413);
Controls.Add(dataGridView);
Controls.Add(panel1);
Name = "FormFuels";
StartPosition = FormStartPosition.CenterParent;
Text = "Топливо";
Load += FormFuels_Load;
panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private Panel panel1;
private Button ButtonDel;
private Button ButtonUpd;
private Button ButtonAdd;
private DataGridView dataGridView;
}
}

View File

@ -0,0 +1,116 @@
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 System.Xml.Linq;
using GasStation.Repositories;
using GasStation.Repositories.Implementations;
using Unity;
namespace GasStation.Forms;
public partial class FormFuels : Form
{
private readonly IUnityContainer _container;
private readonly IFuelRepository _fuelRepository;
public FormFuels(IUnityContainer container, IFuelRepository fuelRepository)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
_fuelRepository = fuelRepository ?? throw new ArgumentNullException(nameof(fuelRepository));
}
private void FormFuels_Load(object sender, EventArgs e)
{
try
{
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormFuel>().ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при добавлении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonUpd_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
try
{
var form = _container.Resolve<FormFuel>();
form.Id = findId;
form.ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при изменении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonDel_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
if (MessageBox.Show("Удалить запись?", "Удаление", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return;
}
try
{
_fuelRepository.DeleteFuel(findId);
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при удалении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList()
{
dataGridView.DataSource = _fuelRepository.ReadFuels();
dataGridView.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
id = 0;
if (dataGridView.SelectedRows.Count < 1)
{
MessageBox.Show("Нет выбранной записи", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
return true;
}
}

View File

@ -0,0 +1,197 @@
<?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>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ButtonUpd.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
oUIOarX/AceT4DvUQEgWAAAAAElFTkSuQmCC
</value>
</data>
</root>

View File

@ -0,0 +1,119 @@
namespace GasStation.Forms
{
partial class FormSupplier
{
/// <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()
{
label1 = new Label();
textBoxBrand = new TextBox();
ButtonSave = new Button();
ButtonCancel = new Button();
checkedListBoxFuelTypes = new CheckedListBox();
label2 = new Label();
SuspendLayout();
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(39, 40);
label1.Name = "label1";
label1.Size = new Size(119, 15);
label1.TabIndex = 0;
label1.Text = "Бренд поставщика:";
//
// textBoxBrand
//
textBoxBrand.Location = new Point(185, 40);
textBoxBrand.Name = "textBoxBrand";
textBoxBrand.Size = new Size(169, 23);
textBoxBrand.TabIndex = 1;
//
// ButtonSave
//
ButtonSave.Location = new Point(39, 257);
ButtonSave.Name = "ButtonSave";
ButtonSave.Size = new Size(116, 30);
ButtonSave.TabIndex = 2;
ButtonSave.Text = "Сохранить";
ButtonSave.Click += ButtonSave_Click;
//
// ButtonCancel
//
ButtonCancel.Location = new Point(187, 257);
ButtonCancel.Name = "ButtonCancel";
ButtonCancel.Size = new Size(125, 30);
ButtonCancel.TabIndex = 3;
ButtonCancel.Text = "Отмена";
ButtonCancel.UseVisualStyleBackColor = true;
ButtonCancel.Click += ButtonCancel_Click;
//
// checkedListBoxFuelTypes
//
checkedListBoxFuelTypes.FormattingEnabled = true;
checkedListBoxFuelTypes.Location = new Point(185, 69);
checkedListBoxFuelTypes.Name = "checkedListBoxFuelTypes";
checkedListBoxFuelTypes.RightToLeft = RightToLeft.No;
checkedListBoxFuelTypes.Size = new Size(169, 94);
checkedListBoxFuelTypes.TabIndex = 4;
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(39, 93);
label2.Name = "label2";
label2.Size = new Size(91, 15);
label2.TabIndex = 5;
label2.Text = "Типы топлива:";
//
// FormSupplier
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(366, 335);
Controls.Add(label2);
Controls.Add(checkedListBoxFuelTypes);
Controls.Add(ButtonCancel);
Controls.Add(ButtonSave);
Controls.Add(textBoxBrand);
Controls.Add(label1);
Name = "FormSupplier";
StartPosition = FormStartPosition.CenterParent;
Text = "Поставщики";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label label1;
private TextBox textBoxBrand;
private Button ButtonSave;
private Button ButtonCancel;
private CheckedListBox checkedListBoxFuelTypes;
private Label label2;
}
}

View File

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics.Contracts;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using GasStation.Entities;
using GasStation.Entities.Enums;
using GasStation.Repositories;
using GasStation.Repositories.Implementations;
namespace GasStation.Forms;
public partial class FormSupplier : Form
{
private readonly ISupplierRepository _supplierRepository;
private int? _supplierlId;
public int Id
{
set
{
try
{
var supplier = _supplierRepository.ReadSupplierById(value);
if (supplier == null)
{
throw new InvalidDataException(nameof(supplier));
}
foreach (SupppliersFuelType elem in Enum.GetValues(typeof(SupppliersFuelType)))
{
if ((elem & supplier.Types) != 0)
{
checkedListBoxFuelTypes.SetItemChecked(checkedListBoxFuelTypes.Items.IndexOf(elem), true);
}
}
textBoxBrand.Text = supplier.Brand;
_supplierlId = value;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при получении данных", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
}
public FormSupplier(ISupplierRepository supplierRepository)
{
InitializeComponent();
_supplierRepository = supplierRepository ?? throw new ArgumentNullException(nameof(supplierRepository));
foreach (SupppliersFuelType fuelType in Enum.GetValues(typeof(SupppliersFuelType)))
{
if (fuelType == SupppliersFuelType.None) continue;
checkedListBoxFuelTypes.Items.Add(fuelType);
}
}
private void ButtonSave_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(textBoxBrand.Text))
{
throw new Exception("Имеются незаполненные поля");
}
if (_supplierlId.HasValue)
{
_supplierRepository.UpdateSupplier(CreateEntity(_supplierlId.Value));
}
else
{
_supplierRepository.CreateSupplier(CreateEntity(0));
}
Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при сохранении",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
private Supplier CreateEntity(int id)
{
SupppliersFuelType fuelType = SupppliersFuelType.None;
foreach (var elem in checkedListBoxFuelTypes.CheckedItems)
{
fuelType |= (SupppliersFuelType)elem;
}
return Supplier.CreateEntity(id, textBoxBrand.Text, fuelType);
}
}

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

@ -0,0 +1,170 @@
namespace GasStation.Forms
{
partial class FormSupplierFuel
{
/// <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()
{
comboBoxSuppliers = new ComboBox();
label1 = new Label();
dateTimePickerData = new DateTimePicker();
label2 = new Label();
ButtonSave = new Button();
ButtonCancel = new Button();
groupBox = new GroupBox();
dataGridView = new DataGridView();
ColumnFuel = new DataGridViewComboBoxColumn();
ColumnQuantity = new DataGridViewTextBoxColumn();
groupBox.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// comboBoxSuppliers
//
comboBoxSuppliers.FormattingEnabled = true;
comboBoxSuppliers.Location = new Point(119, 16);
comboBoxSuppliers.Name = "comboBoxSuppliers";
comboBoxSuppliers.Size = new Size(209, 23);
comboBoxSuppliers.TabIndex = 0;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(13, 21);
label1.Name = "label1";
label1.Size = new Size(76, 15);
label1.TabIndex = 1;
label1.Text = "Поставщик:";
//
// dateTimePickerData
//
dateTimePickerData.Location = new Point(119, 60);
dateTimePickerData.Name = "dateTimePickerData";
dateTimePickerData.Size = new Size(209, 23);
dateTimePickerData.TabIndex = 2;
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(15, 63);
label2.Name = "label2";
label2.Size = new Size(36, 15);
label2.TabIndex = 3;
label2.Text = "Дата:";
//
// ButtonSave
//
ButtonSave.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
ButtonSave.Location = new Point(12, 365);
ButtonSave.Name = "ButtonSave";
ButtonSave.Size = new Size(117, 22);
ButtonSave.TabIndex = 5;
ButtonSave.Text = "Сохранить";
ButtonSave.UseVisualStyleBackColor = true;
ButtonSave.Click += ButtonSave_Click;
//
// ButtonCancel
//
ButtonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
ButtonCancel.Location = new Point(211, 365);
ButtonCancel.Name = "ButtonCancel";
ButtonCancel.Size = new Size(117, 22);
ButtonCancel.TabIndex = 6;
ButtonCancel.Text = "Отменить";
ButtonCancel.UseVisualStyleBackColor = true;
ButtonCancel.Click += ButtonCancel_Click;
//
// groupBox
//
groupBox.Controls.Add(dataGridView);
groupBox.Location = new Point(13, 89);
groupBox.Name = "groupBox";
groupBox.Size = new Size(318, 271);
groupBox.TabIndex = 7;
groupBox.TabStop = false;
groupBox.Text = "Топливо";
//
// dataGridView
//
dataGridView.AllowUserToResizeColumns = false;
dataGridView.AllowUserToResizeRows = false;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Columns.AddRange(new DataGridViewColumn[] { ColumnFuel, ColumnQuantity });
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(3, 19);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.RowHeadersVisible = false;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(312, 249);
dataGridView.TabIndex = 0;
//
// ColumnFuel
//
ColumnFuel.HeaderText = "Топливо";
ColumnFuel.Name = "ColumnFuel";
//
// ColumnQuantity
//
ColumnQuantity.HeaderText = "Количество";
ColumnQuantity.Name = "ColumnQuantity";
//
// FormSupplierFuel
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(342, 399);
Controls.Add(groupBox);
Controls.Add(ButtonCancel);
Controls.Add(ButtonSave);
Controls.Add(label2);
Controls.Add(dateTimePickerData);
Controls.Add(label1);
Controls.Add(comboBoxSuppliers);
Name = "FormSupplierFuel";
StartPosition = FormStartPosition.CenterParent;
Text = "FormSupplierFuel";
groupBox.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private ComboBox comboBoxSuppliers;
private Label label1;
private DateTimePicker dateTimePickerData;
private Label label2;
private Button ButtonSave;
private Button ButtonCancel;
private GroupBox groupBox;
private DataGridView dataGridView;
private DataGridViewComboBoxColumn ColumnFuel;
private DataGridViewTextBoxColumn ColumnQuantity;
}
}

View File

@ -0,0 +1,77 @@
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 GasStation.Entities;
using GasStation.Repositories;
using ProjectGasStation.Entities;
namespace GasStation.Forms;
public partial class FormSupplierFuel : Form
{
private readonly ISuppliersFuelRepository _suppliersFuelRepository;
public FormSupplierFuel(
ISuppliersFuelRepository suppliersFuelRepository,
ISupplierRepository supplierRepository,
IFuelRepository fuelRepository)
{
InitializeComponent();
_suppliersFuelRepository = suppliersFuelRepository ?? throw new ArgumentNullException(nameof(suppliersFuelRepository));
comboBoxSuppliers.DataSource = supplierRepository.ReadSuppliers();
comboBoxSuppliers.DisplayMember = "Name";
comboBoxSuppliers.ValueMember = "Id";
ColumnFuel.DataSource = fuelRepository.ReadFuels();
ColumnFuel.DisplayMember = "Type";
ColumnFuel.ValueMember = "Id";
}
private void ButtonSave_Click(object sender, EventArgs e)
{
try
{
if (comboBoxSuppliers.SelectedIndex < 0 || dataGridView.RowCount < 1)
{
throw new Exception("Имеются незаполненные поля");
}
_suppliersFuelRepository.CreateSuppliersFuel(SuppliersFuel.CreateElement(0,
(int)comboBoxSuppliers.SelectedValue!, dateTimePickerData.Value, CreateListContractorFuelFuelFromDataGrid()));
Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при сохранении",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
private List<SuppliersFuelFuel> CreateListContractorFuelFuelFromDataGrid()
{
var list = new List<SuppliersFuelFuel>();
foreach (DataGridViewRow row in dataGridView.Rows)
{
if (row.Cells["ColumnFuel"].Value == null ||
row.Cells["ColumnQuantity"].Value == null)
{
continue;
}
list.Add(SuppliersFuelFuel.CreateSuppliersFuelFuel(0,
Convert.ToInt32(row.Cells["ColumnFuel"].Value),
Convert.ToInt32(row.Cells["ColumnQuantity"].Value)));
}
return list.GroupBy(x => x.FuelId, x => x.Quantity, (id, counts) =>
SuppliersFuelFuel.CreateSuppliersFuelFuel(0, id, counts.Sum())).ToList();
}
}

View File

@ -0,0 +1,132 @@
<?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>
<metadata name="ColumnFuel.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnQuantity.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnFuel.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnQuantity.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@ -0,0 +1,113 @@
namespace GasStation.Forms
{
partial class FormSupplierFuels
{
/// <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()
{
panel1 = new Panel();
ButtonDel = new Button();
ButtonAdd = new Button();
dataGridViewData = new DataGridView();
panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridViewData).BeginInit();
SuspendLayout();
//
// panel1
//
panel1.Controls.Add(ButtonDel);
panel1.Controls.Add(ButtonAdd);
panel1.Dock = DockStyle.Right;
panel1.Location = new Point(623, 0);
panel1.Name = "panel1";
panel1.Size = new Size(114, 413);
panel1.TabIndex = 0;
//
// ButtonDel
//
ButtonDel.BackgroundImage = Properties.Resources.Минус;
ButtonDel.BackgroundImageLayout = ImageLayout.Stretch;
ButtonDel.Location = new Point(22, 98);
ButtonDel.Name = "ButtonDel";
ButtonDel.Size = new Size(80, 80);
ButtonDel.TabIndex = 1;
ButtonDel.UseVisualStyleBackColor = true;
ButtonDel.Click += ButtonDel_Click;
//
// ButtonAdd
//
ButtonAdd.BackgroundImage = Properties.Resources.Плюс;
ButtonAdd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonAdd.Location = new Point(22, 12);
ButtonAdd.Name = "ButtonAdd";
ButtonAdd.Size = new Size(80, 80);
ButtonAdd.TabIndex = 0;
ButtonAdd.UseVisualStyleBackColor = true;
ButtonAdd.Click += ButtonAdd_Click;
//
// dataGridViewData
//
dataGridViewData.AllowUserToAddRows = false;
dataGridViewData.AllowUserToDeleteRows = false;
dataGridViewData.AllowUserToResizeColumns = false;
dataGridViewData.AllowUserToResizeRows = false;
dataGridViewData.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridViewData.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridViewData.Dock = DockStyle.Fill;
dataGridViewData.Location = new Point(0, 0);
dataGridViewData.MultiSelect = false;
dataGridViewData.Name = "dataGridViewData";
dataGridViewData.ReadOnly = true;
dataGridViewData.RowHeadersVisible = false;
dataGridViewData.RowTemplate.Height = 25;
dataGridViewData.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridViewData.Size = new Size(623, 413);
dataGridViewData.TabIndex = 1;
//
// FormSupplierFuels
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(737, 413);
Controls.Add(dataGridViewData);
Controls.Add(panel1);
Name = "FormSupplierFuels";
StartPosition = FormStartPosition.CenterParent;
Text = "Поставки";
Load += FormSuppliers_Load;
panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridViewData).EndInit();
ResumeLayout(false);
}
#endregion
private Panel panel1;
private Button ButtonDel;
private Button ButtonAdd;
private DataGridView dataGridViewData;
}
}

View File

@ -0,0 +1,95 @@
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 GasStation.Repositories;
using Unity;
namespace GasStation.Forms;
public partial class FormSupplierFuels : Form
{
private readonly IUnityContainer _container;
private readonly ISuppliersFuelRepository _suppliersFuelRepository;
public FormSupplierFuels(IUnityContainer container, ISuppliersFuelRepository suppliersFuelRepository)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
_suppliersFuelRepository = suppliersFuelRepository ?? throw new ArgumentNullException(nameof(suppliersFuelRepository));
}
private void FormSuppliers_Load(object sender, EventArgs e)
{
try
{
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormSupplierFuel>().ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при добавлении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonDel_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
if (MessageBox.Show("Удалить запись?", "Удаление", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return;
}
try
{
_suppliersFuelRepository.DeleteSuppliersFuel(findId);
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при удалении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList()
{
dataGridViewData.DataSource = _suppliersFuelRepository.ReadSuppliersFuels();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["Date"].DefaultCellStyle.Format = "dd.MM.yyyy";
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
id = 0;
if (dataGridViewData.SelectedRows.Count < 1)
{
MessageBox.Show("Нет выбранной записи", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
id = Convert.ToInt32(dataGridViewData.SelectedRows[0].Cells["Id"].Value);
return true;
}
}

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

@ -0,0 +1,129 @@
namespace GasStation.Forms
{
partial class FormSuppliers
{
/// <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()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormSuppliers));
panel1 = new Panel();
ButtonDel = new Button();
ButtonUpd = new Button();
ButtonAdd = new Button();
dataGridView = new DataGridView();
panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// panel1
//
panel1.Controls.Add(ButtonDel);
panel1.Controls.Add(ButtonUpd);
panel1.Controls.Add(ButtonAdd);
panel1.Dock = DockStyle.Right;
panel1.Location = new Point(623, 0);
panel1.Name = "panel1";
panel1.Size = new Size(114, 413);
panel1.TabIndex = 0;
//
// ButtonDel
//
ButtonDel.BackgroundImage = Properties.Resources.Минус;
ButtonDel.BackgroundImageLayout = ImageLayout.Stretch;
ButtonDel.Location = new Point(19, 184);
ButtonDel.Name = "ButtonDel";
ButtonDel.Size = new Size(80, 80);
ButtonDel.TabIndex = 2;
ButtonDel.UseVisualStyleBackColor = true;
ButtonDel.Click += ButtonDel_Click;
//
// ButtonUpd
//
ButtonUpd.BackgroundImage = (Image)resources.GetObject("ButtonUpd.BackgroundImage");
ButtonUpd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonUpd.ForeColor = SystemColors.ControlText;
ButtonUpd.Location = new Point(19, 98);
ButtonUpd.Name = "ButtonUpd";
ButtonUpd.Size = new Size(80, 80);
ButtonUpd.TabIndex = 1;
ButtonUpd.UseVisualStyleBackColor = true;
ButtonUpd.Click += ButtonUpd_Click;
//
// ButtonAdd
//
ButtonAdd.BackgroundImage = (Image)resources.GetObject("ButtonAdd.BackgroundImage");
ButtonAdd.BackgroundImageLayout = ImageLayout.Stretch;
ButtonAdd.Location = new Point(19, 12);
ButtonAdd.Name = "ButtonAdd";
ButtonAdd.Size = new Size(80, 80);
ButtonAdd.TabIndex = 0;
ButtonAdd.UseVisualStyleBackColor = true;
ButtonAdd.Click += ButtonAdd_Click;
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToResizeColumns = false;
dataGridView.AllowUserToResizeRows = false;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(0, 0);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersVisible = false;
dataGridView.RowTemplate.Height = 25;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(623, 413);
dataGridView.TabIndex = 1;
//
// FormSuppliers
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(737, 413);
Controls.Add(dataGridView);
Controls.Add(panel1);
Name = "FormSuppliers";
StartPosition = FormStartPosition.CenterParent;
Text = "Поставщики";
Load += FormSuppliers_Load;
panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private Panel panel1;
private Button ButtonDel;
private Button ButtonAdd;
private DataGridView dataGridView;
private Button ButtonUpd;
}
}

View File

@ -0,0 +1,114 @@
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 System.Xml.Linq;
using GasStation.Repositories;
using Unity;
namespace GasStation.Forms;
public partial class FormSuppliers : Form
{
private readonly IUnityContainer _container;
private readonly ISupplierRepository _supplierRepository;
public FormSuppliers(IUnityContainer container, ISupplierRepository supplierRepository)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
_supplierRepository = supplierRepository ?? throw new ArgumentNullException(nameof(supplierRepository));
}
private void FormSuppliers_Load(object sender, EventArgs e)
{
try
{
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormSupplier>().ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при добавлении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonUpd_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
try
{
var form = _container.Resolve<FormSupplier>();
form.Id = findId;
form.ShowDialog();
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при изменении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonDel_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
return;
}
if (MessageBox.Show("Удалить запись?", "Удаление", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return;
}
try
{
_supplierRepository.DeleteSupplier(findId);
LoadList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при удалении", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList()
{
dataGridView.DataSource = _supplierRepository.ReadSuppliers();
dataGridView.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
id = 0;
if (dataGridView.SelectedRows.Count < 1)
{
MessageBox.Show("Нет выбранной записи", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
return true;
}
}

View File

@ -0,0 +1,716 @@
<?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>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ButtonUpd.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
oUIOarX/AceT4DvUQEgWAAAAAElFTkSuQmCC
</value>
</data>
<data name="ButtonAdd.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
K31V8e7Vof5St9VfHu1aH+UrfVXx7tWh/lK31V8e7Vof5St9VfHu1aH+UrfVXx7tWh/lK31V8e7Vof5S
t9VfHu1aH+UrfVXx7tWh/lK31V8e7Vof5St9VfHu1aH+UrfVXx7tWh/lK31V8e7Vof5St9VfGltd6e1X
PUw5a07SU0aPJ0kRjFnJAtfuq7lc0dl9dVUU71glpZ5IZAKZiA8ZKnHu1aH+UrfVXx7tWh/lK31V8e7V
of5St9VfHu1aH+UrfVXx7tWh/lK31V8e7Vof5St9VfHu1aH+UrfVXx7tWh/lK31V8e7Vof5St9VfHu1a
H+UrfVXx7tWh/lK31V8e7Vof5St9VfHu1aH+UrfVXx7tWh/lK31V8e7Vof5St9VfHu1aH+UrfVXx7tWh
/lK31V8e7Vof5St9VfDctOiUUlTXseoCmI/rjPuW6sniaHIqA01/+pqbMw/djFx9pxNNPVTy1FRK808r
FpJXO0zk9ZPeTwOOTaA0+hMhTtokf/XdubMj+nUdid4y/fB6GPNy703/AAmQzgbkqZ4yf30Df+3x/kJ+
G87/AISn++3daq+NmoPpas/FPj0x2YnPYpxp2A0Wm8opuDRZfTofNsxgc1bunI7FA7xl72SQecc3LbTG
fRqSgb6bMKeQ+hrx/wDu8f5CfhvO/wCEp/vt3WqvjZqD6WrPxT48lO1XNBTKLtPNHEPS7BcKAoAAsALA
c1Qbzyem3eMt/vXHat/s5uUWgau0LnkKi7LSNKPTCRJ/7cKQVB8e5Dp4YM5zsu4X/g6f77YBDAEG4PA9
zqr42ag+lqz8U+PaHojmGs8hgAvatWUjzQAyH7vOx2nY9rE4kmhiIDuqkjgTgEEAg3BFwe6pH2KhD23H
NVU8dXTTU8guk0bIw8zCxx0ElMz08m54HaJ/Sh2T3tV2mtfHvCpOyVH6pvxOCCCQeo+IFlUgFgL8LnHI
WHfN8/jQWlamg23I8H37Yy8BWmiTfFEVVG85F27nVXxs1B9LVn4p7+q7TWvj3hUnZKj9U34nBBBIPUe+
8jFAKvWclQRuo6CRgf2pSEH8r80jbMbN2A4LohUM6qTwBIF8Rh3240X9MXbpXYX2Bew9O7himspljS3R
RlVQ+e127pW2GVuwg8/KDl39l63zqECyyzioT0TgOf5k96UbR7OsnC7PhAEdS368Ex3B37uC9QwSSST3
8soZVPFjuGEAlWwUGRrl2YX2cchUEE+cZ8rr71aSBAQSLrtHCoqKFUAAdQ7nVXxs1B9LVn4p78o2j2dZ
OF2fCAI6lv14JjuDv3cF6hgkkknvvIXQdDlecZkw31FUkCeiBb/1fmrZEijRGJ25GsFHZxOIgKhAFjVp
nuZZGW+xvt19fYMJBBLtgoCqEohDEXW3A244VVRQqgADgB3dO+3Ch83Ny55YYs1yjNABaop3p3I8qI7a
/aGPeUTbvY2IOLqFDKNwBDjr34JTaDXJtwW1reIVBQRlWIu3g77b+3GwwbZZrSgko53hvNhVSW7FWRuD
WJF8cg6qmc50qiwFHT/fbutVfGzUH0tWfinvqJt3sbEHF1ChlG4Ahx178EptBrk24La1u/OwRSx6hjk6
yz+xdFZPA4CyPT9PJ27U56Q/ZfGZSQCAxuRtP4Fzax6j5rYrUkSVIZH2Z1JeOY7w47PMPNhEjnvIUeN7
2cBiAbejiMIiooRAAoG4d4y1l2XU8Qbj6+blcygZnomrdBeSgdKpLdke5/8AtJwDcd2o2j/MnAKMAi3U
3uDjbANyCHG49h9PiFxcC+84gRJI9t0UsxO1cX34S1+icB02iEPHh1YAAAAFgMchPw3nf8JT/fbutVfG
zUH0tWfinvijaP8AMnAKMAi3U3uDjbANyCHG49h9Pf8AJcrbPM7y3LFv/wAXVRxvbqS93P1KDgGNdlAV
G7cvDcMUEMFTTmWZEeV2bpCd5Bvw827DMr1DwOBJCJGWInfbYHDCqFUKoAA3Ad5opOjqFvwYEc1RTw1d
PNBKoaOaNkde1WFiMV2XzZRmFZl0395R1EkJ8+wbA/WN/dKpY+YcThNkn3t+vcesYUKDdbuR1WxJxAJu
QLHv5Nh1XtuBNsRRpIrbYvJte/7QerAiLFtpbsB4YOyG9NsJGwILbIC32VXgL9fNyE/Ded/wlP8Afbut
VfGzUH0tWfinvaqWPmHE4TZJ97fr3HrGFCg3W7kdVsScQCbkCx7/AMjGUmp1BW5qygrl9LsRX+Vn3fdB
xR09PVRSdMt59s9Jfcym+63YMPTFOlaVCXRd0gYosm7dcDEULhlaTYAS+wiXCi/EntPerkEEdWFYOoYd
Y5uWnJP7P1NT5mi2izKCz/8A1oNx+1bdyo2jb7T2YQrte9uD5+BwwXcVO49XWMEkm9z39m2VLWJt1DEU
ccse0yhi97nEaBiWDG6OVB7V7D3HIT8N53/CU/327rVXxs1B9LVn4p70o2jb7T2YQrte9uD5+BwwXcVO
49XWMEkm9z3+R+jRnsTsi9sclGnoMs0PSSVEQapzEtVzXG8dJ4A81kAxSwhmaQSMDDMyh/KTyTfjjMJN
mNYxu2jw8w75QTfoWTrQ7vQeblQ08c+0fVpEm1UUdqqDtJi8IfWtxhWDqGHAjuEfZuDvU8RjZWOzX2vJ
FvEpYiDtptftqptfCqqKAosANw7jkJ+G87/hKf77d1qr42ag+lqz8U96R9m4O9TxGNlY7Nfa8kW8R0zk
jaj1Dl2VjwJ5gZj2RJ75/wCQtipo9i00CuFG54kJW4AtutiJEjjVUXZUDcMVkvSzsepdw75Sy9FMrdR3
Hn1tp46X1RXUAW0Dt09L2GKXeAP3Tde5uQCOo+L8hPw3nf8ACU/327rVXxs1B9LVn4p73cgEdR8R5DtP
FKetz+ZN85NNTX+TQ3dh6W3fVzTP0UbN36mk6SIHrG483LNpr+0shjzenS8+Vkl7cWgfc/8ApO/ANx43
yE/Ded/wlP8AfbutVfGzUH0tWfinxugy+qzavpcvpBeermWKPzbXFj5gN5xlWWUuTZbSUFKuzDSwrEna
Qo4nzniebMZtqQRjgu8+nv1FL0c2yTYPu+vmlijnieKRFdHUq6neCDuIONV6dl0pqCsyttrokbpKZz+v
C+9fs4HxvkJ+G87/AISn++3daq+NmoPpas/FPjfIlpgyzVOo6hNy7VPRX/8AuOPujmdgilj1YZizFjxJ
ue/wSdLGG6+vm5XtKHPciGZUsd6zLAzgAb5IT4a/Va4wrBlBBuCPGuQn4bzv+Ep/vt3WqvjZqD6WrPxT
41k+UVmoM2o8rpP72qkC7VtyIN7OfMoxlWWUmT5bS0NMnR09LEsca+Zes+c8TzZjLdliHVvPiFFP0M1j
4L7jz8o2kjpPULiBLUFcWlpexD+vF/l6vN34KSL9XaTbBUra/A8D3vkJ+G87/hKf77d1qr42ag+lqz8U
+LBSRfq7SbYKlbX4HgeYkKCTjkb0icsyx89q47VWYIBACN8dPxH1vx5pHEaFj1YJLEseJNz36V2VQFtt
OwVb9pwsbSAnpJVG+z9IQSR+zwAxE7SKwcAMrFTbgd17j0g4pJhJHY+EvHm1npel1dkM9BKQkv8AeU0p
/wCVKvgt6Oo+bFRTVNFUz0lVEYqinkaOWM8VZe+m/wCrvIVdnd1W6sAWV78StyOzfu73yE/Ded/wlP8A
fbutVfGzUH0tWfinnkYqBbixAGAhe52nA3++2iDu83C2I2Zgdob1Nj5/P4ib/q7yFXZ3dVurAFle/Erc
js37ubk+0kdXZ6qzITl9GVkqj1OeKxf5uvzYAVQAAAALAc1dUdLJsA+9Q/ae/wAyM6ApbbRgyX4XGDtE
GPZn2De8ewOviNvsxErKGLm7OxZuwX6h6BiGYwSBx9YwCGAI4Hm5YtEtWQe2OgiJqKeO1aii/SRLwf0p
/TAIYAjvgawsQCBwwWuLWAHe+Qn4bzv+Ep/vt3WqvjZqD6WrPxTzyKzKNm20put8G5utpdk/qbPb1bXZ
hFYAlj75mufEQ1hYgEDhgtcWsAMUNDWZrXU9BRRmSpqXCRr/AFJ7ABvJxpTTlFpHJIMtpvfMo25peuSV
vCc81VN0Ue7czcPFKCp6M9G3A8OYgEEEXB4jHKXodtJZn7LpIz/ZdY/6PsglO8x+g8V8Y5CfhvO/4Sn+
+3daq+NmoPpas/FPi7MEUk45LNCe16hObZlFbMatBZG4wRHeE/ePFuZmCqSeAxNK00hduvgOweK0lR0y
Wbwl4+fz82c5XQZzl1Rl1ZCJaeeMq68LdhHnB3g41Vpev0hnD5fVXeNrvS1FrCaP8w4MPF+Qn4bzv+Ep
/vt3WqvjZqD6WrPxT4sSAMck+gvZ80Woszi/4eJg1DCw8Nh/zW8w/V56uo6VthfAX+Z8WR2jcOu4jEUi
yoGH1jm1XpPLtWZO9DWe8YXeCdRdopOph/uOvGcZPmOn8zmy3MI9ieLrHgyKeDoesHxbkQq0h1RmFMxA
NTQAp5zE+8fY3dZtWLmWc5pWp4NTX1Eq+h5CR4tycaBfVlWK+vQrlNO+/q9kuv6g/ZH6xwiJEioihVUA
KoFgAOAA5q2pCL0MZ3nwj4xBO0Em0N46xhWDqGU3B5tc6Ky/WOWdFKRDWQgmlqQN6N2HtU9YxmWW5hku
YT5fmEJhqYTZlPAjqZT1qeo+K5Pm9XkGbUeaUu+Wll2tny1O5kPpBtjIc7yzP8qgzGglDwzD/MrdasOp
h1juOVXWUOn8nkyylkBzGviKKBxhibc0h/ouFUIoUcALeK6B0FV60rOlm24cqge00w3GUj/lx/7nqxR0
lNQUsVNTRJDDCgSNFFlVRwA5qioEKWWxY8B2efG8kkm58Zpalqdu1DxGAQwBB3Hm1xofL9Z0AR7Q1kN/
Y1UBvQ+S3ah6xjNspzLIcxly/MYDDUR9XFXXqdD1qcPIFIUAsx32GEkD3FiCvEHq8SCE2uQL8L407qfP
NI1rT5ZOFDkdNTuNqKX94dvnG/GWcumTSxAZpllXTSdZhtMh+6ce7VolFuBXsewUxxnnLdUyxNDkWXmA
n/qamxYeiNSR9pxU1FTW1MtVVTPPUTNtSSubsx8QeQKQoBZjvsMJIHuLEFeIPV3GhNAVmsagVE+3BlUT
Wkl4NMRxSP8A3bFHRUmV0sNJRwpDDCgWONBYKBzTTrCvaTwGGZnYsxuT43TVJgNm3oeIwCCLjm1ppnJN
VUIo65H9kKC1NNEt5Yj5Q/Z7QeONSZBm2lMzekr02RJuiqQp2HC9nn7R1Yj2C69Hcoga7eUT4iI2I6hf
hc8cbJuWUXbcLeThuCjiRe5858TeVUIFmZjwVRc4MvvmZTsh7KWI3oR1EYj2C6iO+wga7eUTzEhQSTjk
+5ManUzR5jmyPBlY3pFvV6n8sfn68QU9PSQRwQRpHFEoVEQBVVRwAA5pplhW549Qw7tIxZjv8dpqpqYm
+9OsdmHzKmjpBNEwk2luoH2XPYMTyzQzyC6xioK7MxPvVCrv/wD8xmOS5TqGkly6qiFRRBPfEnf0pNwy
N1MO0Y1tyfZto2VpwWq8tY+8qgN8fYsoHD08DgEHvwBY2GNglGbsGCN+2g2i3Cw4YcC4G4kDf6fE5J0W
LbU7VxcAYkZ45GFwvSWs5O4ADERG3aNiURbE3vdjzAMzoiKzu7BURRdmJ4AAcTjQnJIYzDmmo0UuLPFQ
Heqdhm7W/ZwAAOaedade1jwGHdpGLMbk98PiUs6xbgCzlSVUAkm3oxSTPTiSaNdvav7JhcbzffuxlxWX
bERL036ocEFT5O/iMAADdiSOOaN45EV0dSrKwuGB3EEdmNbcjzxGSv00u7e0mXk/gk/dOGDxyPFIjRyR
sVeNwVZWHEEHge+ohuCSB1i544uzNfhIOI6iMMAGNvE3lCbt5YgkKBfCbg0iC5N+lRhvxD1hbmPqDA3B
7N/VzZFkGcamrfYeV05lcf3kh97HEO126saK5Oso0igqGtWZiVs9U43JfisQ/VH8zz1NUsPvUsX/AJDD
MzsWY3J4nx6SaOIgNcsQTZQSbDrwk8SyyOzjYl2dh+r3o4HsxPL+kepiNxCihmB3MS3g4V3ifaViDiCq
SYWO5usc+stAZBq5C86+x65RZKuIDbHYHHB1xqjRmoNISkZhBt0xayVkQJibsB8k+Y976NyNw4jdh1LM
WUXBw9itj4SAXPibyIhANySL2AucLIiuzlhsyW2W6tw4Ylf3zTIbiNQCRwYk8MMwUgcSTYAbyT2DGkuS
TNc4KVWd9JQUh3iAbp5PT5A/njLMryzIaJKHLqWOngTgiDr7SeJPnPPU197pDu7W/wDHj7zRxsFYksd4
UAk4ilSOV5S5ZJCBtndsEfqt2DHQ7MxdTYN/eJbcx7fMcdCC4ZndwrXVSdy8w3EEbiMU9fwWbq4N/wCe
eaGKoieKaNJI3BVkYBlYHqIONVci1JVbdXp6VaSU7zSSX6Fv3TvKYzXKs0yKrNJmlJLSTdSuNz+dGG5h
6O8BGNjYb+AJ44kFyXHm/wAuC1yDbf1+fBYkAWAHYPEnkRCAb3PUBc4R1R2csSrkDa8kjqOCojcvtBVP
hg8D58aX5PdSaudJaaFoKO9xVVF1j/yLxfGleTrTukwssSey662+smALD9wcE55JEjF2OKiqeoNuC9Q/
wCKRoZpVnZVZ7FX4BgN2F6OepkZbMnRbDnqZr/zsMABQFAsAAAO5gqZac+93jyTiKojl4Gx7Dz5nleV5
xQvS5hSxVEDfqSKG+sdhxqTkSA26jTtZbifYdSSR6Ek4/bjNsozbIan2PmtFNSSXIXpB71/Oji6t9Xci
19/DEiMWJAJB4EDDkhrX37IDeKCUQPJ0zqt7EMTYEDGmtBan1bOZKKj6GkKBWq6i6Rn90cX+rGmuSTTe
RFJqsHMqtP15lAiQjyI+H23wAAAAN3PUV6rdIt58rqw7tIxZiST/AIDLEk8ZR+HV5j24jEgQBypIJ3gW
uO8QZg8fvZBtDt68JIkgupvz1lFR19O9PV08U8L+FHIgdT9Rxn3InkVftzZRPLlkp4Rb5oT/AJWN1+o4
zvk61jkG202XmrhW/wCmpLyi3aV3MPswHViRfeOIO4jnRtncfBPidHTVeZTinoaaaqmP/LhQyN/LGRcj
OqMz2ZMxlhyyE8V3TTfYpsPtxkXJZpHI0DCk9l1I3ipqbSsp7VXwV+oYhEoS0pDMDxG6455aqKLdxPYM
T1Ms598bDyR/hqsyNdSQe0YhzFhulW48oYSRJBdWB7jO9IaXz8E5lltPM5/5ltmQeh1s2M35DMvZWkyn
NZ6c8RFOnTJ6LjZYYzTkr1zle0RQR1qD9elkDH/Q2y2KunqsulMVdTT0sg4rNG0Z/wC4DAZWFwQe/NLG
nhOBjLNPahzm39n5TW1Kn9dYiE/1tZcZTyLarrtlq+opMvjPEX6eT7Fsv88ZNyMaToSr1pnzJx8s+zH9
SJb+ZOKShoMspxT0NNDTRDgkSBF+xe4lqoo917nsGJauWQED3i9g/wARBKm4NjiKvnj3NZx5+OEqoZd1
9k9h7maCGojMc0aSI3FXUMD9RxmXJtobMdp5slpkbyoLwH/7ZXFfyHaacE0mYZhSt2FklX7GF8VfIRmq
X9h55Ty+aaBo/wCas2Krkc1zTX2EoKn/AOnOQfsdVxNyaa/gF2yR3/cmhb/3Yk0XrOLwtPZj9UW192+D
pTVo46fzb1SQ/wBBj2r6r/8Ay/m3qcv5cLpLVzcNP5r9dK4/qMQ6E1vPbYyCt3+UFT7xGIeSvX81icqS
IdslTEPuk4peRPWE++aqyyAdY6R5CPsUYpOQY7jWZ+3nWGmC/wA2ZsUfIzomjN51raw9k05A+yIJig0l
pfJbewMoooWHBxEpf/UbnuSwUXJAxJXRL4ALkfUMSVEsnE2HYP8AFo5ZYvAcjEeYyKLMgPnGI6ynbdtW
/e3YBB4eJNIieEwGJcxiAIQM38sSV8732bIMEljdiSf8bBKm4JHowlXUpwe/p34XM5P1kU+jCZhABvVg
cCrpz+vb04EsbcHX7e7JA4nBmiXi6/bj2ZTpu2ifQMf2hGvgxkntJth8xnbcAq4eed/CkY/4PbxJqmxO
yq7IbZ2nbZBPYu43wkhZijoUcC9r3BHaD3uwwCRwJxtP5TfacbT+U32nG0/lN9p5rDuLeJNU2J2VXZDb
O07bIJ7F3G+EkLMUdCjgXte4I7QfFBgeIjjinugRujY7EXRsBvKMv5sBneoQNxTaYjyFYWCnznj4oMDx
EccU90CN0bHYi6NgN5Rl/NgM71CBuKbTEeQrCwU+c8f8HeGKQ3Zd/aCQftGERI12UUKOwf4O8MUhuy7+
0Eg/aMIiRrsooUdg/wDl7//EAE4RAAECAwIHCgsFBwMDBQAAAAECAwAEEQUhBjAxQEFRsRITIDRSYXF0
kpMQFRYiMlBUc4GRoRQjcsHRM0JTYmOCsjVE4SQlQ2CAg5DS/9oACAECAQE/AP8A3agExkgrQMqh8431
vlp+cBSTkIP/AKHftKQlrnZhtJ1VqfkIdwmkEVDaXXOhNB9YdwofP7KWQn8SidlIcwgtVeRxtH4UfrWF
2naTl5mnfgdzshb7671vuqHOsmFCtCakxuE6hG4RyRG5TqgFScilDoJEInJxv0Zl8f8AyGEWxajeSaUf
xAK2iG8JLSR6QZX0pIP0MNYUi7fZUjWUKr9DSGcIbMdyuKbOpaSIamGHxVp1Cx/KoH14pSUJKlEADKTE
zhBZzFQlZeVqbFR88kTGEs45cy0hoaz5xh+cnJn9s+4sHRWg+QgADIOAbuiCSMWBQ1Fx1i6GLYtKX9GY
Uoal+dEvhRkExLn8TZr9DErakhOUDTySrkm5XyPrebtCTkhV91KToTlUfgIm8JnV1TKtBA5a7z8hExMz
E2qr7q3DqJuHQOEmNmkQSRGXHEA5YlbWtCToEPFaR+4vzhEphLLOUTMoLKuV6SYbcbdQFtrStJyFJqPW
U7aUnID75zzjkQL1H4RO4QzkxVLP3CNYvWfjogkqUVKJKjlJNScQokG6Dr05nLzMxKL3bDqmzppkPSIk
sJQaIm29z/URePiIaeafQFtrStJyEGvq6YmZeUbLjzgQkaTE/hE+/VEqC0jln0j0aoJJUVEkqOUm8nEk
kG7JFYJGZgVgU0RLTD8m5u5dxSTpGg9IiQwhYeIbmqMucr9w/pAIIBBu9V2lhAzKktS9HXRlP7qYmJh+
ac3x9wrVz6OgYkXmCSDBP1GaAVgU0QaaIqfBZ9rzdnkJSd8a0tqP+J0RI2jK2gjdNK84ekg3KHqh99mW
aU46sIQMpMWlbr87VtmrTPyUvp1CAAMWDoMHLmgNOiKBN/BbW40sONrKFpyKEWXhAh8pZmqNuZAvIlX6
H1NaFpS9nNbpw1WfQQMqonZ6ZtB3dvKuHooGRPqOppwiAYsq3XJTctTBK2cgVlUj9RDbiHUJW2oKSoVB
GQ+o7Vthqzk7hIC31DzUaudUPPOzDqnXVla1ZSfVlm2o/Zq6Cq2VHzm/zTEtMszbKXWVBSVeobYthMik
tNUU+ofBA1mFKWtalrUVKUaqUcpOa2bZExaJ3dd7ZBvWRl/CIYsGzGQKs74eUs1g2TZhHFGewIm8G5N1
JMuSyvpqn5GJqVfk3i08ncqF41EaxmshaD9nPbtu9J9NGhQ/WJSbYnWUvMqqk/MHUc/ti10yCN6aop9Q
uHJGswpSlqUpSipSjUk5Sc1kZQz020wLgo1UdSRlhttDSEtoSEpSKADgWxICflFJA+9RVTZ59XxgGoBz
WQn3rOf3xu9J9NGhQ/WJWaZnGUvNKqlX05jntrWmizmbqKeX6CfzPMIWtbq1OOKKlqNVE6TigCYIpi8G
Egzj6tKWgB8TwptAbnJlAyJecA+ebWZaLtnP7sXtKP3ifzHPDTrb7aXG1BSFCoIzuenWpCXU85ouSnSo
6hExMPTb63nTVavkBqGLPNGg4vBfjMz7tG08Ke4/N9Yc2+EeAimYnmixbUMg7vTp+4WewTp6DnS1obQp
ayAlIJJOgCLTtBdozJXeG0VDaTq19JxgME4vBfjMz7tG08Ke4/N9Yc2+ERz3QTmIME1FIwetTdASbyvO
A+6J0jk/DOcIbS31Zk2j5qTV06zyc5wX4zM+7RtPCnuPzfWHNucAqSoKSSlSSCkjKCIsm0U2jKhRoHEX
ODn19Bze2LQ8XypKf2q/NbHPr+Ec5JJN5JznBfjMz7tG08Ke4/N9Yc25zZ08uz5pLwqUm5xOtMIWlxCV
pIKVAEHWDmqlJQkqUQABUmLRnlWhNre/cHmtjUkfrnWC/GZn3aNp4U9x+b6w5tzrBufuMk4clVNdGkZr
hJPb20mUQfOdvXzI/wCc7wX4zM+7RtPCnuPzfWHNudNuOMuIdbNFoUFJPOIk5pE7LNvoyLF41HSMzddQ
y0txZolCSSeYRMzC5uYcfXlWa01DQMQBWCKZlgvxiZ92jaeFPcfm+sObceBWCKYvByd3mYVKrPmu3o5l
D9RmeE05uGm5RJvc85f4R+pxABMUug5L8xCTGDHGZr3aNp4U9x+b6w5txwBMUug5L8Wla21JWg0UkhST
qIiSmkTkq0+n99N41HSMxJCQSTQAVJidmjOzbr5yLV5vMkXDhhJJpAAI6NEHJflzACsUuJjnF8YMcZmf
do2nhT3H5vrDm3GhJJpAAI6NEHJflxuDM3uXHZVRuV56OnSMxwhm/s8gpCTRbx3A6NPDArB1fIwfrmIE
bYNxujBfjMz7tG08Ke4/N9Yc24wCsHV8jB+uOl31Ssw0+nK2oHpGkQhaXEJWk1SoAg8xzDCGZ3+0C2D5
rCdz8TeeEATBBp0QBdQ6cx3Jggk1EHJ0eDBfjMz7tG08Ke4/N9Yc24sAmCDTogC6h05hg7M7/Z4bJ85l
RR8Mox7zqWGXHVZEJKj8IUtbq1OL9Jaio9J4IBMG8ARW6K3ZgEmFaxBNYJ8GC/GZn3aNp4U9x+b6w5tx
QBMG8ARW6K3Zhg6+WZ/ezcl9BHxTeMfhG/vVnFsG95YT8Mp4RFQKReAMxEKBJgk/TgYL8Zmfdo2nhT3H
5vrDm3FEVApF4AzEQ24ph9t5N5bWlQ+EJUFpCgagioOOwmf3c4yyDc22VHpVwgSDBpmQNODgvxmZ92ja
eFPcfm+sObcUCQYNMyB0HJFhv7/ZjBJvQCg/23Y603t/tGaX/UKR0Iuz7BfjMz7tG08Ke4/N9Yc259gs
95kyyTkUlY+Nx2Y15wMtOOHIhJUfgIBJFTlN5+OfYL8Zmfdo2nhT3H5vrDm3PsHXd7tMJ/iNqT8r8bbb
hasqZI0o3PaNM/wX4zM+7RtPCnuPzfWHNufWc5vVoSq8lHkjtXY3CZe5s9CeW8kfIE5/gvxmZ92jaeFP
cfm+sObc+3RRRQypIPygEKAIyEYzCk+bKJ0FSz8gIIxdRrEVGsRUaxFRrEVGsRUaxFRrEXa4JGsRUaxF
RrEVGsRUaxFRrEVGsRUaxFRrEVGsRUaxGCxBmZn3aNp4U8R9vm+sObYqNYio1iARrjzdcVGsRUaxFRrE
VGsRUaxFRrEVGsRUaxFRrEVGsRUaxFRrEVGsRUaxFRrHhpBHDN4MSC93IyytbKD9MZhOqszLJ1NrPzMA
UxNmWM/aP3iiW2a+lpV+GGLFsxgCkulZ5S/OP1jxfIeysd2mPF8h7Kx3aY8XyHsrHdpjxfIeysd2mPF8
h7Kx3aY8XyHsrHdpjxfIeysd2mDISB/2rHdpj7BIeysd2mPF8h7Kx3aY8XyHsrHdpjxfIeysd2mPF8h7
Kx3aY8XyHsrHdpjxfIeysd2mPF8h7Kx3aY8XyHsrHdpjxfIeysd2mPF8h7Kx3aYalpdgktMttk5SlIGz
hKkZJaipUsySTUkoFSY8XyHsrHdpjxfIeysd2mPsEh7Kx3aY8XyHsrHdpjxfIeysd2mPF8h7Kx3aY8Xy
HsrHdpjxfIeysd2mPF8h7Kx3aY8XyHsrHdpjxfIeysd2mPF8h7Kx3aY8XyHsrHdpjxfIeysd2mPF8h7K
x3aY8XyHsrHdpjxfIeysd2mPF8h7Kx3aYNnSBFDKsd2mJvBySeSSwCwvRS9PxETUq/JvFl5NFC8aiNYg
xkGIsVW7suVOpunyuxmEx/7g17gf5GCScRIShnpxpi8JJqs6kjLCEIbQlCQAlIoANAHrC2ZAT0mqg+9b
BU2do+MBV0Ek4iwDWyZf+/8AyOMwl/1JHV0/5HE4MJBnH1aQ0B8z6ydSEPOpGRLiwPgcTg9/pTP4nP8A
I4zCb/UUdXT/AJHE4MuBM86g5VtXf2n1iSACTcBC17444vlrUr5muJwe/wBKZ/E5/kcZhOP+vZOtjYo4
mWmHJSYbfR6Taq01jSIlZlmcYQ80qqVfTmPrDCC0ky8uZZtX3roof5UnKcVYIpZMv/f/AJHGYUpo/Kq1
oWPkRipKemZBwrYVQH0kG9KoYwnllJo8y4hX8tFCPKSzOU52DHlJZnKc7BjykszlOdgx5SWZynOwY8pL
M5TnYMeUlmcpzsGPKSzOU52DHlJZnKc7BjykszlOdgx5SWZynOwY8pLM5TnYMeUlmcpzsGPKSzOU52DH
lJZnKc7BjykszlOdgx5SWZynOwY8pLM5TnYMeUlmcpzsGPKSzOU52DEjakpaC1oZKiUAE1TTLwncILOZ
dcaUXN0hZSfMOUR5SWZynOwY8pLM5TnYMeUlmcpzsGPKSzOU52DHlJZnKc7BjykszlOdgx5SWZynOwY8
pLM5TnYMeUlmcpzsGPKSzOU52DHlJZnKc7BjykszlOdgx5SWZynOwY8pLM5TnYMeUlmcpzsGPKSzOU52
DHlJZnKc7BjykszlOdgwcJLM0F0/2GJvCZxYKZVrcfzrvPwEKUta1LWoqUo1KjlOKsdO4suVH9IH534z
ClH3cqvUtQ+Y/wCM/wAF+MzPu0bTwp7j831hzbnyrknoiSRvcnLo5LSB8hjMJUbqzgrkOoP5fnn+C/GZ
n3aNp4U9x+b6w5tz4ILikoGVagn5mkAUxlsNF6zJpOpsq7N+f4LcZmvdo2nhT3H5vrDm3PrLb320pVP9
UK7N+NWgOIUg5FAg/GNyUEoOVJKT8MWBUxdqzGhjBfjEz7pFPmeFPcfm+sObceBUxdqx2DbW+WiV6G2i
fiq7HWuzvFpzKeUrdj++/FAVgUywSMxN3RGDHGZnnbRtPCnuPzfWHNuOArAplgkY7BdmjEw9y3AkdCR/
zjsKGNy/LvctBQelN4xIFYuoCPjFRWtcwTGzSIJIjBe+Zmvdo2nhT3H5vrDm3GgVi6gI+MVFa1xxNBFj
sfZ7Nl0HKUbo9Kr8db8vv9mOEZWiHB8Mv0xAFYuNwitOnMVEg3QdenwYL8Zmfdo2nhT3H5vrDm3GAVi4
3CK06cfLMGamWWP4iwD0aYpTHLQlxCkKFUqBBHMYeZVLvOMqytrKflwgKwKaIAGiphWYEkG7JFYJHgwX
4zM+7RtPCnuPzfWHNuLArApogAaKmFY/BqX3yccfIuaRQfiVmGEktvU6h8ZHk0P4k8ECsCmiDTRFTjxe
YJIME/UcDBfjMz7tG08Ke4/N9Yc24oCsCmiDTRFTmFhyxlrObqKKd88/HJ9MwtuUM3Z7gSKrb89HSmAa
ivABp0RQJvzIHQYOXgYL8Zmfdo2nhT3H5vrDm3FA06IoE35jIypnZxljQpXnfhF5gasxtOU+wzzrQFEE
7tH4Vfpwammb4L8Zmfdo2nhT3H5vrDm3F1NMxwYlKIdm1D0/MR0DKcywjk9+lRMIHnsXnnScueYL8Zmf
do2nhT3H5vrDm3O2mXJh1DLfpOKCREuwiWYbZR6KEgDMlJCklKhUEUIifk1SE24wa7kXoOtJyZ3gvxmZ
92jaeFPcfm+sObc7wakqlc4sa0N/mc0wgkPtUrvyBVxmp6U6RAzrBfjMz7tG08Ke4/N9Yc251LS7k3MN
sN+ks0rqGkwwy3LsoabFEoSAM1tmQ+wTZ3I+6dqpHNrTjgCYIpi8F+MzPu0bTwp7j831hzbmwBMEU8OD
tn7wwZpwUW8PN5kf85taMii0JVbJuOVCtShC0LaWptadytBIUNRGNPNGg4vBfjMz7tG08Ke4/N9Yc2+E
eAimYnmjQfBY9n+MJqih9y3Quc+pMAZvhDZpcT9saT56B94BpSNPwxoME4vBfjMz7tG08Ke4/N9Yc2+E
Rz3QTmIMEw007MOoaaG6Ws0AiQkm5CWQyi+l6lcpRynObasz7A/vjY+4cN38quT+mcYL8Zmfdo2nhT3H
5vrDm3NyaRYVlmTa395NHnBk5CdWdTDDU0ytl1NULFCIn5F2z5gsrvBvQvlDN8F+MzPu0bTwp7j831hz
bm9gWVvqkzj6fMBq0k6Tyj+WeT8gzaEuWnLjlSoZUnXEzLPSj6mXhRSfkRrGbYMuBM68gm9bVR/aeFMO
B6ZfcGRbq1D4nNrGskz7m+ughhB7ZGjogAJAAFAMgz207NatFncnzXE3oXqP6Q+w9LPKadTuVpyj8xms
tMOSkw2+j0kKrTWNIiVmWZxhLzSqpUPlzHgW7aSZSXLKD986CB/Kk5TAFBmtlWU5aTm6VVLCT5yuVzCG
20NIShCQlKRQAZ/admM2i1Q+a4n0F6v+ImJd6VeUy8ncrT8iNYgCsEUzKkSk9NWe4VMqpX0kG9KoYwol
lJ++ZcQr+WihBwls3+r2Im8J1qBTKslP86/0ELWt1aluKKlqNSo5TmAFYIpwLKsly0VhaqoYBvVpVzCG
mm2W0ttpCUpFAB6hn7Ol7RZ3DgooegsZUmJyRmJB3en0/hUMixzQcl+YhJi/KMuyDozMAmKXQcl/hsmx
FzpD0wCljKE5Cv8AQQhCG0hCAEpSKAC4D1HMyzE4ypl5AUk/Q6xFp2Q/ZyioVcY0L1cyseBWKXExzi+F
ZmEkmkAAjo0Qcl+XwXkgAEkmgAvJiysH6bl+cAJypaygfi9TEBQIIBBFCDFp4OkVdkhzln/8/pBBBKSC
CDQg3EY0CNsG43ZmBWDq+Rg/XwSspMTru9sIKjpOhPSYsyxpezwFn7x6l6zo5k6vVNoWTK2gKqG4cAuc
Tl+OsRPWbN2er71NUaHE3pP6YvcmCCTUQcnRmYBMEGnRAF1Dp8Fn4PPzFHJmrTfI/fP6QxLsyrYbZQEI
Ggeq1JStJSoAg3EGJ/BttdVyhDav4Z9E9GqH2H5Vze321Nq59PQcQEmFaxBNYJzIAmDeAIKrr4kbLnZ+
hbRuGzlcVk+GuJCxpSQooDfHf4isvw1er3mGZlstutpWk6CIncGcq5Nyn9Nf5GJiXmJRe4fbU2efIeg8
EQoEmCT9M0VSgMSdlT86AUN7hHLXcPhpMSWD8nLELd+/c1qFw6B6zcbbdQUOIStJygioibwalXaql1qZ
Or0kxNWNaMrUqaLieU3530yxUeEGmZtoceXuGkKcVqSKxK4OTz1C8pLCe0qJOxZCSIUlvfFj99fnH1xM
2fJTn7ZhCjyqUPzETGC7Jvl31I/lWN0IfsK02KkNB0DSg1+hoYcQ4yrcuoU2dSgRtx5IGUwzJzcz+xYc
WNYTQfMwxg3PuULq22R2zEvg3INULm7eP8xoPkIaZaZTuW0JQnUkUHr1SUrBCgCDoMPWNZj16pZAOtPm
bKQ5gxJK/ZuvIPSFCHMFnx+zmkK/EgjYTC8HLTRk3lfQv9RCrFtZH+2J6FpP5wbNtEZZR7s1j7BP+yP9
2Y+wz/skx3aoFn2gf9o/2DCbKtNeSUc+NBthNhWsr/wBPStMIwatBXpOMp+JP5Q3gt/Emz0JRTaTDWDd
mo9IOOfiX+lIZs+Rl6b1LtpI07kV+f8A9AP/xABOEQABAgQABgwKCAQFBAMAAAABAgMABAURBiExQEFR
EhMgIjBSYXGBk7GyFRYyNDVQVHN0kRAUI0JyocHRU2OCkiQzRGLhJUOiwmCAkP/aAAgBAwEBPwD/AO2o
BOQQcUFxsZVp+cbc1x0/MQFpVkUD/wDB5mr0yUuHpppJ4uyur5CH8MKY3cNIeeOsJ2I/8rQ9hnMq/wAm
TbRyrWVfkLQ7hTWnDidab/A2P/a8LrFXd8qdf/pOx7sOTMy5jcmXli2IFxRvCxsrFVyTluY2tHFEbW3x
RGwRqEJKk+StSeZREIn6g35E5MJ5nVQ3Xq015M6s/iCVdohrC2rN+WlhznSQfyMM4aJxbdJqGsoWD+Rt
DGFVGe8p1TR1OII/MXEMTUtMi7Lzbo/2KCuz14taG0lS1BKRlJNgIm8KKTK3CHC+saGhcfPJE1hfPu3E
u02wNZ36v0ETNQn5y+3zTqxxdlZPyFhASBkFvpsbEwcRy4hkEEkWxxfggLKChiI0jEYlq9V5TyJpS08V
zf8A5nHErhnkE3Kn8TRv+RiSrNMn7BiYQVcQ71XyPredqkhTk3mH0oOhOVR5gIncMXl3TJMhA/iOYz0J
ETU3NzqtlMvrdOpRxDmGQbpN7xcWxDFpEElOLERogm54YgHKIkq5VZCwbfK0D7jm/H7iJHC+TesmbbUw
rjeUj9xDTzT6AtpaVoORSTcH1lUKvIUxP27u+IxNpxqPRFQwqn5u6JcfVm9YxrPTog3UoqUSpRxlRNyd
3jhRINgcQg6xiOmMuZSs3NSLm2Szy2labZDzjIYp2F6VWRPN7H+agXHSnKIYfZmW0uMuJcQrIpJuPV03
OSsi0XZh1LaBpOnmEVPCyZmLtyQLLf8AEPlnm1QSVKKlEqUo3Kibk8AIUSCLZI2Wo9GqCRovjy3zMC5g
Wvi+WuJSamZB3bZV1aFaQBiP4hFNwrlpgpanAlh3j/8AbJ59EAggEG4PqurYUS8mVMyoD7wxE/cRznSY
mpqZnXi7MuKcXy5ByAaOBAuYUSk2GiFH8xmgF4Ta+KCBoi5+il1yepRCUnbWNLSjk/CdEU2rSVUb2TC9
8PKbViUnnHqiZmWJRlTr7iW0JykxV8JJmobJmX2TLGQ6Fr59QgAAWHBpVoPRBxnNEm3NFgnHl1blpx1h
xLrS1NuJyKSbERRsKG5kpYndi26cSXMiF/sfU1Uq0rSmdm6brV5DY8pRio1Kbqj22TCsQ8hseSj1Hc2t
uiARFFwkekSlibKnJfIF5VN/uIadbfbS42sLQoXSoG4PqOt15mlI2tADkwob1GgcqofffmnlvPuFbisq
j2DUPVlIrUzSHLC7jCjdbX6p1GJSbl55hL7CwtCtP6H1DXq+imp2hiy5lQ6EA6T+gha1uLU4tRWtZupR
xknNaRQpqrHZg7UwDYuEXvyJES2DFHl0gFjbVcZwlX5ZINDo5FjIy/8AYIncEZB5JMqVS69GMqQecGJy
TmZCYLEwjYrGMalDWDmtLqkzSZjbGt8hX+Y1oUP0MSU9LVCXS+wvZIV8wdRGvP6/XU0xvaWbKmVjEMoQ
OMYUpa1qWtRUtRJUo4ySc1psiajPMywJAWbrOpIyw002w2httIShAASkaANxXqYmpyKkgfbNgqaPLq6Y
BuAc1pdTmKTM7a1vkKxON6Fj94k5yXn5dD7CtkhQ6QdR5c9rdZbpMvisp9wWbR+p5BDjjjzi3XFla1m6
lHSeCAJggjg8DUAz80vSllIH9R/43U82lqfm205ETDoHMFHNqPVXqTMbMXUwsgOo/Ucohl5qZaQ60sLQ
sXSoZCM7qVQYpkot93RiSnSpRyARNzT89MLmHzdaz0AaAODN74tQtGgg6uDwM87nPdI7Tuql6Tnvine9
9Ii9jkHNaFADMTe+LULRg9WTTHtofV/h3D1ajp5jpgEHOXHENNqcWoJSkEqJ0ARWKq5VpsuYwyi4ZQdW
s8p4QHkgng8DPO5z3SO07qpek574p3vfSCBHLivrg8mYg8kE3FrYowWrJWBT31b5I+wUdIH3ejOcKqvt
zhkGVbxBBeI0nQno05zgZ53Oe6R2ndVL0nPfFO97OApaFJWhRSpJBSoZQRFDqqarJhZsHkb11PLr5jm9
eqopckVII2526Why6T0Rjxkkkk3JOknOcDPO5z3SO07qpek574p3vZzSqiulTqH03KDvXU60/uIbcQ62
lxCgpK0gpI0g5qpSUJK1EAJBJJ0ARVqiqqTy38e1jetDUkfvnWBnnc57pHad1UvSc98U73s6wRqmJVPd
Vkupnm0pzXC6pbUwmRbO/eF3ORA/fO8DPO5z3SO07qpek574p3vZ0065LutvNGzjagpJ5RFPnW6hJtTD
eRacY1HSMzfebl2XHnDZDaSpR5BE3NuT007MueU4q9tQ0DgALwRbMsDPO5z3SO07qpek574p3vcOBeCL
cHglUNomlyazvH98jkWMo6RmeGE/sGWpFBxu79z8IyDpPAAEwBiHJo1wchvlOY7EkRgd53OH+U32ndVL
0nPfFO97hgCYAxDk0a4OQ3yng0rW2tLjZstCgpJ1EYxFPnEVCSZmEffTcjUdIzFSkpSVKIAAuTFQnFVC
efmTkWreDUkYhuwkk2gAEDTbRCsmPKTmABMbHETB1jHeMDvPJv3Tfad1UvSc98U73uFCSTaAAQNNtEKy
Y8pPC4Hz2wdeklnEr7RvnGJQzHCmd+q0xTaTZcwdrHN97dgXg6B8jCuXLmITkJjHfUoQrEcUYGedznuk
dp3VS9Jz3xTve4QC8HQPkYVy5eGlZpclNMzKMrSwrnGkdIhtaHUJWg3SoAg6wcwwpnPrNULQN0S6An+p
WNW6CSYKTYDSIAxBJ05jsTCgSbjGDBxg6x9GBnnc57pHad1UvSc98U73uDCSYKTYDSIAxBJ05hgpOfWa
WGlHfy6ij+nKnh5h5Esw68vyW0KUeYC8LcW8tbqzdbiitXOo33IBMEEi2kaIvi7I2WLMAkwrXBVp0wVX
Fsn0YGedznukdp3VS9Jz3xTve4IAmCCRbSNEXxdkbLFmGCkyZeplomyZhsj+pOMcPhZNbRSi0DjfcSjo
yns3RF0i0Ywka75iLXxwoEnXeFEg5dFjuMDPO5z3SO07qpek574p3vcERdItGMJGu+Yi18cNPLlphqYQ
LltaVjoMJUlaQpJuFAEHkPDYYTG2T7DAOJpoqPOs/sN0CQYNr4sySq2Xc4Gedznukdp3VS9Jz3xTve4I
EgwbXxZkDischjBuZ+s0eWJNy2C2f6DYflw1Yf8ArNWnHMo20oHMje/pn2Bnnc57pHad1UvSc98U73s+
wLf3k5Lk5FpcA/ELHs4V90MMOunI2hSj0C8AlQucpxnpz7Azzuc90jtO6qXpOe+Kd72fYKPbVWEo0PNL
T0jffpwuETpZos4RlUjYf3kJz/Azzuc90jtO6qXpOe+Kd72fUp3aKpJOXtZ9IPMrent4XDBzY0ttH8SY
QOgAnP8AAzzuc90jtO6qXpOe+Kd72fFRRZYypIUOiEqCkhQyEXHCYaK3kii+IrcV8gB+sbHg7jWIuNYi
41iLjWIuNYi41iLjWI3uuCU8YGLjWIuNYi41iLjWIuNYi41iLjWIuNYi41iLjWIwLIM3Oe6R2ndVIjwn
PYx5073jFxrEXGsQCnWI3uuLjWIuNYi41iLjWIuNYi41iLjWIuNYi41iLjWIuNYi41iLjWIuNYi41j6d
jBG7VjSeaKYvbadKL4zDZ/8AEcJhkq83KJ4rTh/uI/aAADwNHoExVbOqUWpe/l6V/h/eJbB6jyyRaVQ4
eM5vyfnHgumexS3VJjwXTPYpbqkx4LpnsUt1SY8F0z2KW6pMeC6Z7FLdUmPBdM9iluqTHgumexS3VJg0
ymn/AEUt1SY8GUz2KW6pMeC6Z7FLdUmPBdM9iluqTHgumexS3VJjwXTPYpbqkx4LpnsUt1SY8F0z2KW6
pMeC6Z7FLdUmPBdM9iluqTHgumexS3VJjwXTPYpbqkwzKSksSWWGmiRjKEBN/lulU2nLUVKlJdSlEkkt
pJJMeC6Z7FLdUmPBdM9iluqTHgum+xS3VJjwXTPYpbqkx4LpnsUt1SY8F0z2KW6pMeC6Z7FLdUmPBdM9
iluqTHgumexS3VJjwXTPYpbqkx4LpnsUt1SY8F0z2KW6pMeC6Z7FLdUmPBdM9iluqTHgumexS3VJjwXT
PYpbqkx4LpnsUt1SY8F0z2KW6pMGlUsixkpbqkxPYJ06YSTLXlnNGxxp6UmJyTmZCYLEwjYrGMEZFDWD
Csd8eU3jEEngMHl7OiyR1NW/tNuEwwJ8KM8ksO8YKieApkialPsy2MJUbrOpKcsNtoaQlCEhKUgBIGQA
esMIKamoyC7D7ZkFbR5RlHTCVG2KCSeAwYN6HK/1988Jhf6Wb+FT3lcDgagGfmVaUsADpP8Ax6yfQG5h
9AyIecSOhRHA4K+hGPxu988JhgP+rN/Cp7yuBwPdSipPNk43GLjnSfWJISCSbACHHNtddc47i1f3G/A4
K+hGOVTnfPCYYi1TYOuW7FHgZSadkppqZb8ppV7axpHSIk5xifl0PsKuhY6QdR5R6wwoqyJWVVKNKu+8
mxt9xByk8/BYMi1DlOZZ+azwmGiLTMkvW24PkRwVPqU5THSuXXYK8tCsaVRL4ZSakj6ww62rTsbLTHjb
R+M71Zjxto/Gd6sx420fjO9WY8baPxnerMeNtH4zvVmPG2j8Z3qzHjbR+M71Zjxto/Gd6sx420fjO9WY
8baPxnerMeNtH4zvVmPG2j8Z3qzHjbR+M71Zjxto/Gd6sx420fjO9WY8baPxnerMeNtH4zvVmPG2j8Z3
qzHjbR+M71ZinVqRqi3ES5WS2AVbJJTl3T2FFJYedZWp3ZNrUhVmycaTYx420fjO9WY8baPxnerMeNtH
4zvVmPG2j8Z3qzHjbR+M71Zjxto/Gd6sx420fjO9WY8baPxnerMeNtH4zvVmPG2j8Z3qzHjbR+M71Zjx
to/Gd6sx420fjO9WY8baPxnerMeNtH4zvVmPG2j8Z3qzHjbR+M71Zjxto/Gd6swcLqOBiLx5A2YnsMHX
ElEkyW7/APccsSOZIha1uLUtaitajdSlG5J4KgI2ujSQ1sg/3Y+Ew0QSzJOanFp/uF/0z/Azzuc90jtO
6qXpOe+Kd72fLNkqPJFPb2qQlW+Iw2PknhML2yukhX8N9Cvnvf1z/Azzuc90jtO6qXpOe+Kd72fJQXVo
bGVa0pHSbQAAAOErzJfo84gZQ0Vf2b79IGfYF+dznukdp3VS9Jz3xTvez6jMl+rySP5wV/Zvv04VxCXW
1oVkUkg9MbBTZLasqFFJ5wbcGkXMb0jJaDmFiYwN87nNW0t2+Z3VS9Jz3xTve4dIuY3pGS0HhcEmdtqy
nNDLKj0qNuGrrH1asTaNCl7YP6xfggLmBbKBzRdOXHi0QcfD2NiYOI5cQyCMDSfrc5ytN9p3VS9Jz3xT
ve4YC5gWygc0XTlx4tEHHwuBjGxlpp/juhA5kD/nhsMpfYzMrMAYloU2edJuO3gUp2UaAR0xdN735hmC
b3i4tiGLSIJKcWIjRGBhvOTnukdp3VS9Jz3xTve4VKdlGgEdMXTe9+YcMTYExQZYytIlUEWUW9mrnXvu
GwolfrNIdUBdTJDo/py/lwAFzGI4hijZWxm98wxwokGwOIQdYxHTGWMDPO5z3SO07qpek574p3vcIBcx
iOIYo2VsZvfh5OWM5OS8v/FcSk82n8oAAFhwziEutqQsXSpJBGsGH2Fyr7rC/KaWpB6N0BcwLXxfI6YA
F7i5hWjWBj4cQokEWyRstR6NUEjRfHlv9GBnnc57pHad1UvSc98U73uDAuYFr4vkdMAC9xcwrRrAx8Pg
hKbdPuzBG9YbsPxL/wCMwwuk9oqCJkDezCLH8SMXZuQLwm18UEDRFzw4FzCiUmw0Qo/mNxgZ53Oe6R2n
dVL0nPfFO97ggLwm18UEDRFzmGDcmZOlNXFlPfaqH4sn5ZhhHI/XqW6Ei7jX2iOdOUdIgEEA7hJtzRYJ
x5dWZJVoPRBxncYGedznukdp3VS9Jz3xTve4JJtzRYJx5dWY06TNQn2JbQtd1/hTjMAAAAZBmNYkfB1S
eZAsgnZt/hV+2Tc3NrZvgZ53Oe6R2ndVL0nPfFO97g7m1sxwOkdi29OrGNf2bf4RlPScywsp/wBYkkzS
Bv5cknlQcvyzzAzzuc90jtO6qXpOe+Kd72dsMOTT7bDQ37qgkdOmJWWblJdphsWS2gJHRmSkpWkpUAUq
BBB0gxU5BVMnnZY32IOybOtByZ3gZ53Oe6R2ndVL0nPfFO97O8EKdslOT6xrba/9j+maYU0wzklt7abu
y91cqkaRANxnWBnnc57pHad1UvSc98U73s6lJV2emmpZrynFWvqGk9ES0u1KMNsNCyG0hIHNmtfpfgye
OwFmHrqb5NaeGAJggjg8DPO5z3SO07qpek574p3vZsATBBH04KUsy0uZx1NnHxvAfut/85tVqc3VJJbC
sSsrauKoZDDjbjLi2nElK0KKVDURwpvfFqFo0EHVweBnnc57pHad1UvSc98U73vpEXscg5rQoAZib3xa
haNBB1fRQaUapOgLH2DNlO8upPTAAAsM3wqpBeR9fYTdbabOgfeSNPOOFB5IJ4PAzzuc90jtO6qXpOe+
Kd730ggRy4r64PJmIPJBMMMPTT7bDKdk44bJEUyntUyTRLt47Y1q4yjlOcERhDRzTJnbWk/4Z1W9/wBi
uL+2cYGedznukdp3VS9Jz3xTvezc4hGDVFMgz9ZfTaYdGQ/cTq59edTUszOS7jDydkhYsRFTpr1Kmiw5
jScba+Mn99eb4Gedznukdp3VS9Jz3xTvezfBiibepM/MJ3iTdlB0njH9M8qdNYqkqWXcRyoWMqVaxE3K
TEhMLl302Wn5KGsZtgc6lFRfbJxuMXH9J/53U06H5uZdGRx9xQ5irNqBQzVHdueBEsg9YRo5tcJSEgAA
AAWAGe1ikMVaX2Ct66jG25qP7GJiXfk31sPo2DiDjH6jkzWUmnZGaZmW/KbVe2sZCOkRJzjE/LofYVsk
LHSDqO4wlq6ZGUVLtq+3fSQBxUnKr9oAAAGa0SiO1Z3ZrumWQd+vjHiphppthtLbaQhCAAlIyADP6xR2
KsxZW8dQDtbgyjkOsRNSsxJPqYfRsFp+RGsckAXgi2ZBOsgRIVGdpbxXLrsD5aDjSqJfDKUUn/ES7rav
9tlj9DBwvpH888m1xO4YuLSUybBR/Mc/RIhxxx5xTjq1LWs3UpWMnMALwRbcUShu1ZwOLuiWSd8rSu2h
P7wyy1LtIaaQEIQLJSMgHqGp0qVqrG1PCyh5DgyoMT9NmqY/tMwnWULHkuDWIOQ3ynMdiSIx5Rl7IVkA
zMAmAMQ5NGuDkN8p+gm0UPB1yoFL80FIlsoTkLn7JhttDSEoQkJSkWAAsAPUc5Jy0/LqYfQFoV8wdYMV
ehTNJUVi7svoc0p5Ffvw4BMbHETB1jHeFaNYzMJJNoABA020QrJjyk/QASQACSTYAC5JiiYL7EomZ9IJ
yoYygcq9Z5PUykpWkpUAQRYgxWMFCnZP08YsqmCe5+0EFKilQKVJNikixB4UJyExjvqUIViOLMwLwdA+
RhXLl+iSkZuovbVLN7I/eUcSU85ij0CVpYDh+1mCMbhGTkSNHqmq0OSqqbrG1vAb11OXp1iKlSZ6lK+3
Rdu+J1ONJ/Y8HsTCgSbjGDBxg6xmYSTBSbAaRAGIJOmLxSsFpmbs7OXYa4n31ftEtKy8myGmG0toGQD1
WtCXElKkhSSLEEXBip4ItOXckFBpX8JXkHm1RMyszJO7VMNKaXoByHmOQ8AEmFa4KtOmCq4tkzIAmCCR
bSNEFQtj0ZDFOotQqdi02G2jleWLA82uKXQJGmWWlO2vaXV5egaPV8xLS820Wn20uIOhQvFQwPyrkHbf
ynDi6FRNSs1JObCZZW0rRcYjzHIdyLXxwoEnXeFEg5dFjmirbEGJCiVOoJSW2i2gm+2Ob0dGkxTsF5CT
Ice/xLo0rG9B5E+s3WWn0FDqErQcqVC4MTuCEk9dUqtUuri+Uj5GJygVaSuVMF1HHa335ZYBB+lKrZcz
abdmF7Bltbq+KgFRiTwTqMxYzCkS6NXlr+QxRIYPUynkLS1trg++5vj+w9cTlLp8/wCcS6FnjWsr5jHE
1gYwq5lZlbZ4qxsx+hiZwarMtchlLyRpbVf8jYw626wrYvNraVqWkp7YuDwxUkZSIl5Cfm7bRKuuA6Qm
w+ZxRLYI1N6xeW0wP71fliiVwSpbFi9s5hX+82T8hDLDMugIZbQ2nUkAD16tCHElKkhQOUEXEP4P0eYx
rk2wdaN53bQ9gbT1f5T77Z5wofmIdwMmR/lTiFfiQU9hMOYJ1lHkhhz8KyO0CF4PVtGWTJ5loP6wqkVZ
OWRf6E37INMqfsMz1So8G1P2Ga6pUCl1Q/6GZ6siEUWsLySLvTYdphODVcX/AKYJ53E/oTDeCFVV5bsu
jpUo9kNYF5NtnTyhDdvzJMM4JUhs3WHXfxrt3bRL0unStizKsoI0hIv8/wD8Af/Z
</value>
</data>
</root>

View File

@ -0,0 +1,108 @@
namespace GasStation.Forms
{
partial class FormSuppliersFuelDistributionReport
{
/// <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()
{
ButtonFile = new Button();
labelFileName = new Label();
dateTimePicker = new DateTimePicker();
label1 = new Label();
ButtonBuild = new Button();
SuspendLayout();
//
// ButtonFile
//
ButtonFile.Location = new Point(12, 22);
ButtonFile.Name = "ButtonFile";
ButtonFile.Size = new Size(75, 23);
ButtonFile.TabIndex = 0;
ButtonFile.Text = "Выбрать";
ButtonFile.UseVisualStyleBackColor = true;
ButtonFile.Click += ButtonFile_Click;
//
// labelFileName
//
labelFileName.AutoSize = true;
labelFileName.Location = new Point(93, 26);
labelFileName.Name = "labelFileName";
labelFileName.Size = new Size(38, 15);
labelFileName.TabIndex = 1;
labelFileName.Text = "Файл";
//
// dateTimePicker
//
dateTimePicker.Location = new Point(71, 65);
dateTimePicker.Name = "dateTimePicker";
dateTimePicker.Size = new Size(151, 23);
dateTimePicker.TabIndex = 2;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(12, 71);
label1.Name = "label1";
label1.Size = new Size(36, 15);
label1.TabIndex = 3;
label1.Text = "Дата:";
//
// ButtonBuild
//
ButtonBuild.Location = new Point(12, 101);
ButtonBuild.Name = "ButtonBuild";
ButtonBuild.Size = new Size(210, 27);
ButtonBuild.TabIndex = 4;
ButtonBuild.Text = "Сформировать";
ButtonBuild.UseVisualStyleBackColor = true;
ButtonBuild.Click += ButtonBuild_Click;
//
// FormSuppliersFuelDistributionReport
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(236, 154);
Controls.Add(ButtonBuild);
Controls.Add(label1);
Controls.Add(dateTimePicker);
Controls.Add(labelFileName);
Controls.Add(ButtonFile);
Name = "FormSuppliersFuelDistributionReport";
StartPosition = FormStartPosition.CenterParent;
Text = "FormSuppliersFuelDistributionReport";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Button ButtonFile;
private Label labelFileName;
private DateTimePicker dateTimePicker;
private Label label1;
private Button ButtonBuild;
}
}

View File

@ -0,0 +1,69 @@
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 GasStation.Reports;
using Unity;
namespace GasStation.Forms;
public partial class FormSuppliersFuelDistributionReport : Form
{
private string _fileName = string.Empty;
private readonly IUnityContainer _container;
public FormSuppliersFuelDistributionReport(IUnityContainer container)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
}
private void ButtonBuild_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(_fileName))
{
throw new Exception("Отсутствует имя файла для отчета");
}
if
(_container.Resolve<ChartReport>().CreateChart(_fileName, dateTimePicker.Value))
{
MessageBox.Show("Документ сформирован",
"Формирование документа",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Возникли ошибки при формировании документа.Подробности в логах",
"Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при создании отчета",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonFile_Click(object sender, EventArgs e)
{
var sfd = new SaveFileDialog()
{
Filter = "Pdf Files | *.pdf"
};
if (sfd.ShowDialog() == DialogResult.OK)
{
_fileName = sfd.FileName;
labelFileName.Text = Path.GetFileName(_fileName);
}
}
}

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

@ -2,10 +2,59 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Deterministic>True</Deterministic>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<Deterministic>True</Deterministic>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql" Version="8.0.5" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
<PackageReference Include="Serilog" Version="4.0.2" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="Unity" Version="5.11.10" />
<PackageReference Include="Unity.Microsoft.Logging" Version="5.11.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,3 +1,12 @@
using GasStation.Repositories.Implementations;
using GasStation.Repositories;
using Unity.Lifetime;
using Unity;
using Unity.Microsoft.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
namespace GasStation
{
internal static class Program
@ -11,7 +20,37 @@ namespace GasStation
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
Application.Run(CreateContainer().Resolve<FormGasStation>());
}
private static IUnityContainer CreateContainer()
{
var container = new UnityContainer();
container.AddExtension(new LoggingExtension(CreateLoggerFactory()));
container.RegisterType <ICashierRepository, CashierRepository>();
container.RegisterType <IFuelRepository, FuelRepository>();
container.RegisterType <IFuelSalesRepository, FuelSalesRepository>();
container.RegisterType <ISuppliersFuelRepository, SuppliersFuelRepository>();
container.RegisterType <ISupplierRepository, SupplierRepository>();
container.RegisterType<IConnectionString, ConnectionString>();
return container;
}
private static LoggerFactory CreateLoggerFactory()
{
var loggerFactory = new LoggerFactory();
loggerFactory.AddSerilog(new LoggerConfiguration()
.ReadFrom.Configuration(new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build())
.CreateLogger());
return loggerFactory;
}
}
}

View File

@ -0,0 +1,113 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программой.
// Исполняемая версия:4.0.30319.42000
//
// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
// повторной генерации кода.
// </auto-generated>
//------------------------------------------------------------------------------
namespace GasStation.Properties {
using System;
/// <summary>
/// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
/// </summary>
// Этот класс создан автоматически классом StronglyTypedResourceBuilder
// с помощью такого средства, как ResGen или Visual Studio.
// Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
// с параметром /str или перестройте свой проект VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GasStation.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Перезаписывает свойство CurrentUICulture текущего потока для всех
/// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Поиск локализованного ресурса типа System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Заправка {
get {
object obj = ResourceManager.GetObject("Заправка", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Поиск локализованного ресурса типа System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Карандаш {
get {
object obj = ResourceManager.GetObject("Карандаш", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Поиск локализованного ресурса типа System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Минус {
get {
object obj = ResourceManager.GetObject("Минус", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Поиск локализованного ресурса типа System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Плюс {
get {
object obj = ResourceManager.GetObject("Плюс", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Поиск локализованного ресурса типа System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Плюсик {
get {
object obj = ResourceManager.GetObject("Плюсик", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@ -0,0 +1,136 @@
<?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>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Плюсик" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Плюсик.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Карандаш" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Карандаш.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Заправка" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Заправка.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Минус" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Минус.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Плюс" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Плюс.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Repositories;
using Microsoft.Extensions.Logging;
namespace GasStation.Reports;
internal class ChartReport
{
private readonly ISuppliersFuelRepository _suppliersFuelRepository;
private readonly IFuelRepository _fuelRepository;
private readonly ILogger<ChartReport> _logger;
public ChartReport(ISuppliersFuelRepository suppliersFuelRepository, IFuelRepository fuelRepository, ILogger<ChartReport> logger)
{
_suppliersFuelRepository = suppliersFuelRepository ?? throw new ArgumentNullException(nameof(suppliersFuelRepository));
_fuelRepository = fuelRepository ?? throw new ArgumentNullException(nameof(fuelRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public bool CreateChart(string filePath, DateTime dateTime)
{
try
{
new PdfBuilder(filePath)
.AddHeader("Поставки топлива")
.AddPieChart($"Поставленные виды топлива на {dateTime:dd.MM.yyyy}", GetData(dateTime))
.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<(string Caption, double Value)> GetData(DateTime dateTime)
{
var fuelNames = _fuelRepository.ReadFuels()
.ToDictionary(f => f.Id, f => f.Type);
return _suppliersFuelRepository
.ReadSuppliersFuels(dateFrom: dateTime.Date, dateTo: dateTime.Date.AddDays(1))
.SelectMany(x => x.SuppliersFuelFuel)
.GroupBy(x => x.FuelId)
.Select(g => (Caption: fuelNames[g.Key].ToString(), Value: (double)g.Sum(x => x.Quantity)))
.ToList();
}
}

View File

@ -0,0 +1,85 @@
using GasStation.Repositories;
using Microsoft.Extensions.Logging;
namespace GasStation.Reports;
internal class DocReport
{
private readonly ICashierRepository _cashierRepository;
private readonly IFuelRepository _fuelRepository;
private readonly ISupplierRepository _supplierRepository;
private readonly ILogger<DocReport> _logger;
public DocReport(ICashierRepository cashierRepository, IFuelRepository fuelRepository,
ISupplierRepository supplierRepository, ILogger<DocReport> logger)
{
_cashierRepository = cashierRepository ?? throw new ArgumentNullException(nameof(cashierRepository));
_fuelRepository = fuelRepository ?? throw new ArgumentNullException(nameof(fuelRepository));
_supplierRepository = supplierRepository ?? throw new ArgumentNullException(nameof(supplierRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public bool CreateDoc(string filePath, bool includeCashier, bool includeFuel, bool includeSupplier)
{
try
{
var builder = new WordBuilder(filePath).AddHeader("Документ со справочниками");
if (includeCashier)
{
builder.AddParagraph("Кассиры").AddTable([2400, 2400, 2400], GetCashier());
}
if (includeFuel)
{
builder.AddParagraph("Топливо").AddTable([2400, 2400], GetFuel());
}
if (includeSupplier)
{
builder.AddParagraph("Поставщики").AddTable([2400, 2400], GetSupplier());
}
builder.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<string[]> GetCashier()
{
return [
["Имя", "Фамилия", "Должность"],
.. _cashierRepository
.ReadCashiers()
.Select(x => new string[] { x.FirstName, x.LastName, x.CashierPost.ToString() }),
];
}
private List<string[]> GetFuel()
{
return [
["Цена", "Тип"],
.. _fuelRepository
.ReadFuels()
.Select(x => new string[] { x.Cost.ToString(), x.Type.ToString() }),
];
}
private List<string[]> GetSupplier()
{
return [
["Бренд", "Типы поставляемого топлива"],
.. _supplierRepository
.ReadSuppliers()
.Select(x => new string[] { x.Brand, x.Types.ToString() }),
];
}
}

View File

@ -0,0 +1,316 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace GasStation.Reports;
internal class ExcelBuilder
{
private readonly string _filePath;
private readonly SheetData _sheetData;
private readonly MergeCells _mergeCells;
private readonly Columns _columns;
private uint _rowIndex = 0;
public ExcelBuilder(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
_filePath = filePath;
_sheetData = new SheetData();
_mergeCells = new MergeCells();
_columns = new Columns();
_rowIndex = 1;
}
public ExcelBuilder AddHeader(string header, int startIndex, int count)
{
CreateCell(startIndex, _rowIndex, header, StyleIndex.BoldTextWithoutBorder);
for (int i = startIndex + 1; i < startIndex + count; ++i)
{
CreateCell(i, _rowIndex, "", StyleIndex.SimpleTextWithoutBorder);
}
_mergeCells.Append(new MergeCell()
{
Reference = new StringValue($"{GetExcelColumnName(startIndex)}{_rowIndex}:{GetExcelColumnName(startIndex + count - 1)}{_rowIndex}")
});
_rowIndex++;
return this;
}
public ExcelBuilder AddParagraph(string text, int columnIndex)
{
CreateCell(columnIndex, _rowIndex++, text, StyleIndex.SimpleTextWithoutBorder);
return this;
}
public ExcelBuilder AddTable(int[] columnsWidths, List<string[]> data)
{
if (columnsWidths == null || columnsWidths.Length == 0)
{
throw new ArgumentNullException(nameof(columnsWidths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != columnsWidths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
uint counter = 1;
int coef = 2;
_columns.Append(columnsWidths.Select(x => new Column
{
Min = counter,
Max = counter++,
Width = x * coef,
CustomWidth = true
}));
for (var j = 0; j < data.First().Length; ++j)
{
CreateCell(j, _rowIndex, data.First()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
for (var i = 1; i < data.Count - 1; ++i)
{
for (var j = 0; j < data[i].Length; ++j)
{
CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder);
}
_rowIndex++;
}
for (var j = 0; j < data.Last().Length; ++j)
{
CreateCell(j, _rowIndex, data.Last()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
return this;
}
public void Build()
{
using var spreadsheetDocument = SpreadsheetDocument.Create(_filePath, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
GenerateStyle(workbookpart);
workbookpart.Workbook = new Workbook();
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
if (_columns.HasChildren)
{
worksheetPart.Worksheet.Append(_columns);
}
worksheetPart.Worksheet.Append(_sheetData);
var sheets = spreadsheetDocument.WorkbookPart!.Workbook.AppendChild(new Sheets());
var sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Лист 1"
};
sheets.Append(sheet);
if (_mergeCells.HasChildren)
{
worksheetPart.Worksheet.InsertAfter(_mergeCells,
worksheetPart.Worksheet.Elements<SheetData>().First());
}
}
private static void GenerateStyle(WorkbookPart workbookPart)
{
var workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
workbookStylesPart.Stylesheet = new Stylesheet();
var fonts = new Fonts()
{
Count = 2,
KnownFonts = BooleanValue.FromBoolean(true)
};
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme()
{
Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor)
}
});
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme()
{
Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor)
},
Bold = new Bold() { Val = true }
});
workbookStylesPart.Stylesheet.Append(fonts);
// Default Fill
var fills = new Fills() { Count = 1 };
fills.Append(new Fill
{
PatternFill = new PatternFill()
{
PatternType = new EnumValue<PatternValues>(PatternValues.None)
}
});
workbookStylesPart.Stylesheet.Append(fills);
// Default Border
var borders = new Borders() { Count = 2 };
borders.Append(new Border
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
});
borders.Append(new Border
{
LeftBorder = new LeftBorder() { Style = BorderStyleValues.Thin },
RightBorder = new RightBorder() { Style = BorderStyleValues.Thin },
TopBorder = new TopBorder() { Style = BorderStyleValues.Thin },
BottomBorder = new BottomBorder() { Style = BorderStyleValues.Thin },
DiagonalBorder = new DiagonalBorder()
});
workbookStylesPart.Stylesheet.Append(borders);
// Default cell format and a date cell format
var cellFormats = new CellFormats() { Count = 4 };
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Right,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
workbookStylesPart.Stylesheet.Append(cellFormats);
}
private enum StyleIndex
{
SimpleTextWithoutBorder = 0,
SimpleTextWithBorder = 1,
BoldTextWithoutBorder = 2,
BoldTextWithBorder = 3,
}
private void CreateCell(int columnIndex, uint rowIndex, string text, StyleIndex styleIndex)
{
var columnName = GetExcelColumnName(columnIndex);
var cellReference = columnName + rowIndex;
var row = _sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex! == rowIndex);
if (row == null)
{
row = new Row() { RowIndex = rowIndex };
_sheetData.Append(row);
}
var newCell = row.Elements<Cell>().FirstOrDefault(c => c.CellReference != null &&
c.CellReference.Value == columnName + rowIndex);
if (newCell == null)
{
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.CellReference?.Value != null &&
cell.CellReference.Value.Length == cellReference.Length)
{
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
}
newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
}
newCell.CellValue = new CellValue(text);
newCell.DataType = CellValues.String;
newCell.StyleIndex = (uint)styleIndex;
}
private static string GetExcelColumnName(int columnNumber)
{
columnNumber += 1;
int dividend = columnNumber;
string columnName = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (dividend - modulo) / 26;
}
return columnName;
}
}

View File

@ -0,0 +1,77 @@
using System.Text;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.Rendering;
namespace GasStation.Reports;
internal class PdfBuilder
{
private readonly string _filePath;
private readonly Document _document;
public PdfBuilder(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
_filePath = filePath;
_document = new Document();
DefineStyles();
}
public PdfBuilder AddHeader(string header)
{
_document.AddSection().AddParagraph(header, "NormalBold");
return this;
}
public PdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data)
{
if (data == null || data.Count == 0)
{
return this;
}
var chart = new Chart(ChartType.Pie2D);
var series = chart.SeriesCollection.AddSeries();
series.Add(data.Select(x => x.Value).ToArray());
var xseries = chart.XValues.AddXSeries();
xseries.Add(data.Select(x => x.Caption).ToArray());
chart.DataLabel.Type = DataLabelType.Percent;
chart.DataLabel.Position = DataLabelPosition.OutsideEnd;
chart.Width = Unit.FromCentimeter(16);
chart.Height = Unit.FromCentimeter(12);
chart.TopArea.AddParagraph(title);
chart.XAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.HasMajorGridlines = true;
chart.PlotArea.LineFormat.Width = 1;
chart.PlotArea.LineFormat.Visible = true;
chart.TopArea.AddLegend();
_document.LastSection.Add(chart);
return this;
}
public void Build()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var renderer = new PdfDocumentRenderer(true)
{
Document = _document
};
renderer.RenderDocument();
renderer.PdfDocument.Save(_filePath);
}
private void DefineStyles()
{
var headerStyle = _document.Styles.AddStyle("NormalBold", "Normal");
headerStyle.Font.Bold = true;
headerStyle.Font.Size = 14;
}
}

View File

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Repositories;
using GasStation.Repositories.Implementations;
using Microsoft.Extensions.Logging;
namespace GasStation.Reports;
internal class TableReport
{
private readonly ISuppliersFuelRepository _suppliersFuelRepository;
private readonly IFuelSalesRepository _fuelSalesRepository;
private readonly ILogger<TableReport> _logger;
internal static readonly string[] item = ["Дата", "Количество пришло", "Количество ушло"];
public TableReport(ISuppliersFuelRepository suppliersFuelRepository,
IFuelSalesRepository fuelSalesRepository, ILogger<TableReport> logger)
{
_suppliersFuelRepository = suppliersFuelRepository ?? throw new ArgumentNullException(nameof(suppliersFuelRepository));
_fuelSalesRepository = fuelSalesRepository ?? throw new ArgumentNullException(nameof(fuelSalesRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public bool CreateTable(string filePath, int fuelId, DateTime startDate, DateTime endDate)
{
try
{
new ExcelBuilder(filePath)
.AddHeader("Сводка по движению топлива", 0, 3)
.AddParagraph($"за период {startDate:dd.MM.yyyy} по {endDate:dd.MM.yyyy}", 0)
.AddTable([10, 15, 15], GetData(fuelId, startDate, endDate))
.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<string[]> GetData(int fuelId, DateTime startDate, DateTime endDate)
{
var suppliersData = _suppliersFuelRepository
.ReadSuppliersFuels(startDate, endDate, fuelId)
.Select(x => new { x.Date, CountIn = x.SuppliersFuelFuel.FirstOrDefault(y => y.FuelId == fuelId)?.Quantity, CountOut = (int?)null })
.Union(
_fuelSalesRepository
.ReadFuelSale(startDate, endDate, fuelId)
.Select(x => new { Date = x.SaleDate, CountIn = (int?)null, CountOut = x.FuelFuelSale.FirstOrDefault(y => y.FuelId == fuelId)?.Quantity })
)
.OrderBy(x => x.Date);
var groupedData = suppliersData
.GroupBy(x => x.Date)
.Select(g => new
{
Date = g.Key,
TotalIn = g.Sum(x => x.CountIn),
TotalOut = g.Sum(x => x.CountOut)
})
.OrderBy(x => x.Date);
return
new List<string[]>() { item }
.Union(groupedData
.Select(x => new string[] { x.Date.ToString("dd.MM.yyyy"), x.TotalIn?.ToString("N0") ?? string.Empty, x.TotalOut?.ToString("N0") ?? string.Empty }))
.Union(
new[] { new string[] { "Всего", groupedData.Sum(x => x.TotalIn)?.ToString("N0") ?? string.Empty, groupedData.Sum(x => x.TotalOut)?.ToString("N0") ?? string.Empty } }
)
.ToList();
}
}

View File

@ -0,0 +1,102 @@
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
namespace GasStation.Reports;
internal class WordBuilder
{
private readonly string _filePath;
private readonly Document _document;
private readonly Body _body;
public WordBuilder(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
_filePath = filePath;
_document = new Document();
_body = _document.AppendChild(new Body());
}
public WordBuilder AddHeader(string header)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
var runProperties = run.AppendChild(new RunProperties());
runProperties.AppendChild(new Bold());
run.AppendChild(new Text(header));
return this;
}
public WordBuilder AddParagraph(string text)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new Text(text));
return this;
}
public WordBuilder AddTable(int[] widths, List<string[]> data)
{
if (widths == null || widths.Length == 0)
{
throw new ArgumentNullException(nameof(widths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != widths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
var table = new Table();
table.AppendChild(new TableProperties(
new TableBorders(
new TopBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new BottomBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new LeftBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new RightBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideHorizontalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideVerticalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 }
)
));
// Заголовок
var tr = new TableRow();
for (var j = 0; j < widths.Length; ++j)
{
tr.Append(new TableCell(
new TableCellProperties(new TableCellWidth()
{
Width =
widths[j].ToString()
}),
new Paragraph(new Run(new RunProperties(new Bold()), new
Text(data.First()[j])))));
}
table.Append(tr);
// Данные
table.Append(data.Skip(1).Select(x =>
new TableRow(x.Select(y => new TableCell(new Paragraph(new
Run(new Text(y))))))));
_body.Append(table);
return this;
}
public void Build()
{
using var wordDocument = WordprocessingDocument.Create(_filePath, WordprocessingDocumentType.Document);
var mainPart = wordDocument.AddMainDocumentPart();
mainPart.Document = _document;
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities;
namespace GasStation.Repositories;
public interface ICashierRepository
{
IEnumerable<Cashier> ReadCashiers();
Cashier ReadCashierById(int id);
void CreateCashier(Cashier cashier);
void UpdateCashier(Cashier cashier);
void DeleteCashier(int id);
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GasStation.Repositories;
public interface IConnectionString
{
public string ConnectionString { get; }
}

View File

@ -0,0 +1,16 @@
using GasStation.Entities;
namespace GasStation.Repositories;
public interface IFuelRepository
{
IEnumerable<Fuel> ReadFuels();
Fuel ReadFuelById(int id);
void CreateFuel(Fuel fuel);
void UpdateFuel(Fuel fuel);
void DeleteFuel(int id);
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities;
namespace GasStation.Repositories;
public interface IFuelSalesRepository
{
IEnumerable<FuelSale> ReadFuelSale(DateTime? dateFrom = null, DateTime? dateTo = null, int? gasStationId = null,
int? fuelId = null, int ? cashierId = null);
void CreateFuelSale(FuelSale fuelSale);
void DeleteFuelSale(int id);
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities;
namespace GasStation.Repositories;
public interface ISupplierRepository
{
IEnumerable<Supplier> ReadSuppliers();
Supplier ReadSupplierById(int id);
void CreateSupplier(Supplier supplier);
void UpdateSupplier(Supplier supplier);
void DeleteSupplier(int id);
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GasStation.Entities;
namespace GasStation.Repositories;
public interface ISuppliersFuelRepository
{
IEnumerable<SuppliersFuel> ReadSuppliersFuels(DateTime? dateFrom = null, DateTime? dateTo = null, int? suppliersId = null,
int? fuelId = null);
void CreateSuppliersFuel(SuppliersFuel suppliersFuel);
void DeleteSuppliersFuel(int id);
}

View File

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using GasStation.Entities;
using GasStation.Entities.Enums;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Npgsql;
namespace GasStation.Repositories.Implementations;
public class CashierRepository : ICashierRepository
{
private readonly IConnectionString _connectionString;
private readonly ILogger<CashierRepository> _logger;
public CashierRepository(IConnectionString connectionString, ILogger<CashierRepository> logger)
{
_connectionString = connectionString;
_logger = logger;
}
public void CreateCashier(Cashier cashier)
{
_logger.LogInformation("Добавление объекта");
_logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(cashier));
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryInsert = @"
INSERT INTO Cashier (FirstName, LastName, CashierPost)
VALUES (@FirstName, @LastName, @CashierPost)";
connection.Execute(queryInsert, cashier);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при добавлении объекта");
throw;
}
}
public void DeleteCashier(int id)
{
_logger.LogInformation("Удаление объекта");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryDelete = @"
DELETE FROM Cashier
WHERE Id=@id";
connection.Execute(queryDelete, new { id });
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при удалении объекта");
throw;
}
}
public Cashier ReadCashierById(int id)
{
_logger.LogInformation("Получение объекта по идентификатору");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT * FROM Cashier
WHERE Id=@id";
var cashier = connection.QueryFirst<Cashier>(querySelect, new { id });
_logger.LogDebug("Найденный объект: {json}",
JsonConvert.SerializeObject(cashier));
return cashier;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при поиске объекта");
throw;
}
}
public IEnumerable<Cashier> ReadCashiers()
{
_logger.LogInformation("Получение всех объектов");
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = "SELECT * FROM Cashier";
var cashier = connection.Query<Cashier>(querySelect);
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(cashier));
return cashier;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при чтении объектов");
throw;
}
}
public void UpdateCashier(Cashier cashier)
{
_logger.LogInformation("Редактирование объекта");
_logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(cashier));
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryUpdate = @"
UPDATE Cashier
SET
FirstName=@FirstName,
LastName=@LastName,
CashierPost=@CashierPost
WHERE Id=@Id";
connection.Execute(queryUpdate, cashier);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при редактировании объекта");
throw;
}
}
}

View File

@ -0,0 +1,6 @@
namespace GasStation.Repositories.Implementations;
public class ConnectionString : IConnectionString
{
string IConnectionString.ConnectionString => "Server=localhost,5432;Database=egov;Uid=postgres;Pwd=postgres;";
}

View File

@ -0,0 +1,121 @@
using GasStation.Entities;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Npgsql;
using Dapper;
using System.Data.SqlClient;
namespace GasStation.Repositories.Implementations;
public class FuelRepository : IFuelRepository
{
private readonly IConnectionString _connectionString;
private readonly ILogger<FuelRepository> _logger;
public FuelRepository(IConnectionString connectionString, ILogger<FuelRepository> logger)
{
_connectionString = connectionString;
_logger = logger;
}
public void CreateFuel(Fuel fuel)
{
_logger.LogInformation("Добавление объекта");
_logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(fuel));
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryInsert = @"
INSERT INTO Fuel (Cost, Type)
VALUES (@Cost, @Type)";
connection.Execute(queryInsert, fuel);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при добавлении объекта");
throw;
}
}
public void DeleteFuel(int id)
{
_logger.LogInformation("Удаление объекта");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryDelete = @"
DELETE FROM Fuel
WHERE Id=@id";
connection.Execute(queryDelete, new { id });
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при удалении объекта");
throw;
}
}
public Fuel ReadFuelById(int id)
{
_logger.LogInformation("Получение объекта по идентификатору");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT * FROM Fuel
WHERE Id=@id";
var fuel = connection.QueryFirst<Fuel>(querySelect, new { id });
_logger.LogDebug("Найденный объект: {json}", JsonConvert.SerializeObject(fuel));
return fuel;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при поиске объекта");
throw;
}
}
public IEnumerable<Fuel> ReadFuels()
{
_logger.LogInformation("Получение всех объектов");
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = "SELECT * FROM Fuel";
var fuels = connection.Query<Fuel>(querySelect);
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(fuels));
return fuels;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при чтении объектов");
throw;
}
}
public void UpdateFuel(Fuel fuel)
{
_logger.LogInformation("Редактирование объекта");
_logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(fuel));
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryUpdate = @"
UPDATE Fuel
SET
Cost=@Cost,
Type=@Type
WHERE Id=@Id";
connection.Execute(queryUpdate, fuel);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при редактировании объекта");
throw;
}
}
}

View File

@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using GasStation.Entities;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Npgsql;
using ProjectGasStation.Entities;
namespace GasStation.Repositories.Implementations;
public class FuelSalesRepository : IFuelSalesRepository
{
private readonly IConnectionString _connectionString;
private readonly ILogger<FuelSalesRepository> _logger;
public FuelSalesRepository(IConnectionString connectionString, ILogger<FuelSalesRepository> logger)
{
_connectionString = connectionString;
_logger = logger;
}
public void CreateFuelSale(FuelSale fuelSale)
{
_logger.LogInformation("Добавление объекта");
_logger.LogDebug("Объект: {json}",
JsonConvert.SerializeObject(fuelSale));
try
{
using var connection = new
NpgsqlConnection(_connectionString.ConnectionString);
connection.Open();
using var transaction = connection.BeginTransaction();
var queryInsert = @"
INSERT INTO FuelSale (CashierId, SaleDate, TotalPrice)
VALUES (@CashierId, @SaleDate, @TotalPrice);
SELECT MAX(Id) FROM FuelSale";
var fuelSaleId =
connection.QueryFirst<int>(queryInsert, fuelSale, transaction);
var querySubInsert = @"
INSERT INTO FuelFuelSale (FuelSaleId, FuelId, Quantity, Price)
VALUES (@FuelSaleId, @FuelId, @Quantity, @Price)";
foreach (var elem in fuelSale.FuelFuelSale)
{
connection.Execute(querySubInsert, new
{
fuelSaleId,
elem.FuelId,
elem.Quantity,
elem.Price
}, transaction);
}
transaction.Commit();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при добавлении объекта");
throw;
}
}
public void DeleteFuelSale(int id)
{
_logger.LogInformation("Удаление объекта");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
connection.Open();
using var transaction = connection.BeginTransaction();
var queryDeleteSub = @"
DELETE FROM FuelFuelSale
WHERE FuelSaleId = @id";
connection.Execute(queryDeleteSub, new { id }, transaction);
var queryDelete = @"
DELETE FROM FuelSale
WHERE Id = @id";
connection.Execute(queryDelete, new { id }, transaction);
transaction.Commit();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при удалении объекта");
throw;
}
}
public IEnumerable<FuelSale> ReadFuelSale(DateTime? dateFrom = null, DateTime? dateTo = null, int? gasStationId = null, int? fuelId = null, int? cashierId = null)
{
_logger.LogInformation("Получение всех объектов");
try
{
var builder = new QueryBuilder();
if (dateFrom.HasValue)
{
builder.AddCondition("fs.SaleDate >= @dateFrom");
}
if (dateTo.HasValue)
{
builder.AddCondition("fs.SaleDate <= @dateTo");
}
if (fuelId.HasValue)
{
builder.AddCondition("ffs.FuelId = @fuelId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = $@"SELECT
fs.*,
CONCAT(s.LastName, ' ', s.FirstName) as CashierName,
ffs.FuelId,
ffs.Quantity,
f.Type as FuelName
FROM FuelSale fs
LEFT JOIN Cashier s on s.Id = fs.CashierId
INNER JOIN FuelFuelSale ffs on ffs.FuelSaleId = fs.Id
LEFT JOIN Fuel f on f.id = ffs.FuelId
{builder.Build()}";
var salesDict = new Dictionary<int, List<FuelFuelSale>>();
var fuelSales = connection.Query<FuelSale, FuelFuelSale, FuelSale>(querySelect,
(sale, fuelSale) =>
{
if (!salesDict.TryGetValue(sale.Id, out var fss))
{
fss = [];
salesDict.Add(sale.Id, fss);
}
fss.Add(fuelSale);
return sale;
}, splitOn: "FuelId", param: new { dateFrom, dateTo, fuelId });
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(fuelSales));
return salesDict.Select(x =>
{
var fs = fuelSales.First(y => y.Id == x.Key);
fs.SetFuelFuelSale(x.Value);
return fs;
}).ToArray();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при чтении объектов");
throw;
}
}
}

View File

@ -0,0 +1,35 @@
using System.Text;
namespace GasStation.Repositories.Implementations;
internal class QueryBuilder
{
private readonly StringBuilder _builder;
public QueryBuilder()
{
_builder = new();
}
public QueryBuilder AddCondition(string condition)
{
if (_builder.Length > 0)
{
_builder.Append(" AND ");
}
_builder.Append(condition);
return this;
}
public string Build()
{
if (_builder.Length == 0)
{
return string.Empty;
}
return $"WHERE {_builder}";
}
}

View File

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using GasStation.Entities;
using GasStation.Entities.Enums;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Npgsql;
namespace GasStation.Repositories.Implementations;
public class SupplierRepository : ISupplierRepository
{
private readonly IConnectionString _connectionString;
private readonly ILogger<SupplierRepository> _logger;
public SupplierRepository(IConnectionString connectionString, ILogger<SupplierRepository> logger)
{
_connectionString = connectionString;
_logger = logger;
}
public void CreateSupplier(Supplier supplier)
{
_logger.LogInformation("Добавление объекта");
_logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(supplier));
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryInsert = @"
INSERT INTO Supplier (Brand, Types)
VALUES (@Brand, @Types)";
connection.Execute(queryInsert, supplier);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при добавлении объекта");
throw;
}
}
public void DeleteSupplier(int id)
{
_logger.LogInformation("Удаление объекта");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryDelete = @"
DELETE FROM Supplier
WHERE Id=@id";
connection.Execute(queryDelete, new { id });
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при удалении объекта");
throw;
}
}
public Supplier ReadSupplierById(int id)
{
_logger.LogInformation("Получение объекта по идентификатору");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT * FROM Supplier
WHERE Id=@id";
var supplier = connection.QueryFirst<Supplier>(querySelect, new { id });
_logger.LogDebug("Найденный объект: {json}",
JsonConvert.SerializeObject(supplier));
return supplier;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при поиске объекта");
throw;
}
}
public IEnumerable<Supplier> ReadSuppliers()
{
_logger.LogInformation("Получение всех объектов");
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = "SELECT * FROM Supplier";
var suppliers = connection.Query<Supplier>(querySelect);
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(suppliers));
return suppliers;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при чтении объектов");
throw;
}
}
public void UpdateSupplier(Supplier supplier)
{
_logger.LogInformation("Редактирование объекта");
_logger.LogDebug("Объект: {json}",
JsonConvert.SerializeObject(supplier));
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryUpdate = @"
UPDATE Supplier
SET
Brand=@Brand,
Types=@Types
WHERE Id=@Id";
connection.Execute(queryUpdate, supplier);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при редактировании объекта");
throw;
}
}
}

View File

@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using GasStation.Entities;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Npgsql;
using ProjectGasStation.Entities;
namespace GasStation.Repositories.Implementations;
public class SuppliersFuelRepository : ISuppliersFuelRepository
{
private readonly IConnectionString _connectionString;
private readonly ILogger<SuppliersFuelRepository> _logger;
public SuppliersFuelRepository(IConnectionString connectionString, ILogger<SuppliersFuelRepository> logger)
{
_connectionString = connectionString;
_logger = logger;
}
public void CreateSuppliersFuel(SuppliersFuel suppliersFuel)
{
_logger.LogInformation("Добавление объекта");
_logger.LogDebug("Объект: {json}",
JsonConvert.SerializeObject(suppliersFuel));
try
{
using var connection = new
NpgsqlConnection(_connectionString.ConnectionString);
connection.Open();
using var transaction = connection.BeginTransaction();
var queryInsert = @"
INSERT INTO SuppliersFuel (SuppliersId, Date)
VALUES (@SuppliersId, @Date);
SELECT MAX(Id) FROM SuppliersFuel";
var suppliersFuelId =
connection.QueryFirst<int>(queryInsert, suppliersFuel, transaction);
var querySubInsert = @"
INSERT INTO SuppliersFuelFuel (SuppliersFuelId, FuelId, Quantity)
VALUES (@SuppliersFuelId, @FuelId, @Quantity)";
foreach (var elem in suppliersFuel.SuppliersFuelFuel)
{
connection.Execute(querySubInsert, new
{
suppliersFuelId,
elem.FuelId,
elem.Quantity
}, transaction);
}
transaction.Commit();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при добавлении объекта");
throw;
}
}
public void DeleteSuppliersFuel(int id)
{
_logger.LogInformation("Удаление объекта");
_logger.LogDebug("Объект: {id}", id);
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
connection.Open();
using var transaction = connection.BeginTransaction();
var queryDeleteSub = @"
DELETE FROM SuppliersFuelFuel
WHERE SuppliersFuelId = @id";
connection.Execute(queryDeleteSub, new { id }, transaction);
var queryDelete = @"
DELETE FROM SuppliersFuel
WHERE Id = @id";
connection.Execute(queryDelete, new { id }, transaction);
transaction.Commit();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при удалении объекта");
throw;
}
}
public IEnumerable<SuppliersFuel> ReadSuppliersFuels(DateTime? dateFrom = null, DateTime? dateTo = null, int? suppliersId = null, int? fuelId = null)
{
_logger.LogInformation("Получение всех объектов");
try
{
var builder = new QueryBuilder();
if (dateFrom.HasValue)
{
builder.AddCondition("cf.Date >= @dateFrom");
}
if (dateTo.HasValue)
{
builder.AddCondition("cf.Date <= @dateTo");
}
if (fuelId.HasValue)
{
builder.AddCondition("cff.FuelId = @fuelId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = $@"SELECT
cf.*,
c.Brand as SuppliersBrand,
cff.FuelId,
cff.Quantity,
f.Type as FuelName
FROM SuppliersFuel cf
LEFT JOIN Supplier c on c.Id = cf.SuppliersId
INNER JOIN SuppliersFuelFuel cff on cff.SuppliersFuelId = cf.Id
LEFT JOIN Fuel f on f.Id = cff.FuelId
{builder.Build()}";
var suppliersDict = new Dictionary<int, List<SuppliersFuelFuel>>();
var suppliersFuels = connection.Query<SuppliersFuel, SuppliersFuelFuel, SuppliersFuel>(querySelect,
(suppliers, suppliersFuel) =>
{
if (!suppliersDict.TryGetValue(suppliers.Id, out var ccf))
{
ccf = [];
suppliersDict.Add(suppliers.Id, ccf);
}
ccf.Add(suppliersFuel);
return suppliers;
}, splitOn: "FuelId", param: new { dateFrom, dateTo, fuelId });
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(suppliersFuels));
return suppliersDict.Select(x =>
{
var cf = suppliersFuels.First(y => y.Id == x.Key);
cf.SetSuppliersFuelFuel(x.Value);
return cf;
}).ToArray();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при чтении объектов");
throw;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -0,0 +1,15 @@
{
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/gas_log.txt",
"rollingInterval": "Day"
}
}
]
}
}