diff --git a/ShoeStore/Entities/Employee.cs b/ShoeStore/Entities/Employee.cs index aa5e8c3..53c50a9 100644 --- a/ShoeStore/Entities/Employee.cs +++ b/ShoeStore/Entities/Employee.cs @@ -11,16 +11,13 @@ public class Employee public int Id { get; private set; } public DateTime Date { get; private set; } public int NumberStorage { get; private set; } - //public int StorageSize { get; private set; } - public static Employee CreateEntity(int id, DateTime date,int numberStorage) { return new Employee { Id = id, Date = date, - NumberStorage = numberStorage, - //StorageSize = storageSize + NumberStorage = numberStorage }; } } diff --git a/ShoeStore/Entities/Receipt.cs b/ShoeStore/Entities/Receipt.cs index 7dd2962..9c849bf 100644 --- a/ShoeStore/Entities/Receipt.cs +++ b/ShoeStore/Entities/Receipt.cs @@ -12,10 +12,10 @@ public class Receipt public int Id { get; private set; } public ProductType ProductType { get; private set; } public DateTime DateOfReceipt { get; private set; } - public int NumberOfPairsReceived { get; private set; } - //public int StorageSize { get; private set; } + public int NumberOfPairsReceived { get; private set; } + public int ProductId { get; private set; } - public static Receipt CreateOperation(int id,ProductType productType, DateTime date,int numberOfPairsReceived) + public static Receipt CreateOperation(int id,ProductType productType, DateTime date,int numberOfPairsReceived, int productId) { return new Receipt { @@ -23,6 +23,7 @@ public class Receipt ProductType = productType, DateOfReceipt = date, NumberOfPairsReceived = numberOfPairsReceived, + ProductId = productId }; } diff --git a/ShoeStore/Entities/Sale.cs b/ShoeStore/Entities/Sale.cs index 299931d..b93babc 100644 --- a/ShoeStore/Entities/Sale.cs +++ b/ShoeStore/Entities/Sale.cs @@ -1,9 +1,12 @@ -using ShoeStore.Entities.Enums; +using DocumentFormat.OpenXml.Office2010.Excel; +using ShoeStore.Entities.Enums; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Unity; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace ShoeStore.Entities; @@ -11,23 +14,30 @@ public class Sale { public int Id { get; private set; } public DateTime DateOfSale { get; private set; } - - public int SalesNumber { get; private set; } public IEnumerable Product { get; private set; } = []; - public static Sale CreateOperation(int id, int salesNumber, DateTime date, IEnumerable product) + public static Sale CreateOperation(int id, DateTime date, IEnumerable product) { return new Sale { Id = id, DateOfSale = date, - SalesNumber = salesNumber, Product = product }; } + public static Sale CreateOperation(TempProductSale tempProductSale, IEnumerable products) + { + return new Sale + { + Id = tempProductSale.Id, + DateOfSale = tempProductSale.DateOfSale, + Product = products + }; + } + } diff --git a/ShoeStore/Entities/TempProductSale.cs b/ShoeStore/Entities/TempProductSale.cs new file mode 100644 index 0000000..4498636 --- /dev/null +++ b/ShoeStore/Entities/TempProductSale.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShoeStore.Entities; + +public class TempProductSale +{ + public int Id { get; private set; } + public DateTime DateOfSale { get; private set; } + public int ProductId { get; private set; } + public int SalesNumber { get; private set; } +} diff --git a/ShoeStore/Forms/FormDistributionReport.Designer.cs b/ShoeStore/Forms/FormDistributionReport.Designer.cs new file mode 100644 index 0000000..d544028 --- /dev/null +++ b/ShoeStore/Forms/FormDistributionReport.Designer.cs @@ -0,0 +1,113 @@ +namespace ShoeStore.Forms +{ + partial class FormDistributionReport + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + buttonSelectFileName = new Button(); + labelFileName = new Label(); + label1 = new Label(); + dateTimePicker = new DateTimePicker(); + buttonCreate = new Button(); + SuspendLayout(); + // + // buttonSelectFileName + // + buttonSelectFileName.BackColor = Color.FromArgb(192, 255, 192); + buttonSelectFileName.Location = new Point(10, 17); + buttonSelectFileName.Margin = new Padding(3, 2, 3, 2); + buttonSelectFileName.Name = "buttonSelectFileName"; + buttonSelectFileName.Size = new Size(113, 22); + buttonSelectFileName.TabIndex = 0; + buttonSelectFileName.Text = "Выбрать"; + buttonSelectFileName.UseVisualStyleBackColor = false; + buttonSelectFileName.Click += ButtonSelectFileName_Click; + // + // labelFileName + // + labelFileName.AutoSize = true; + labelFileName.Location = new Point(157, 20); + labelFileName.Name = "labelFileName"; + labelFileName.Size = new Size(36, 15); + labelFileName.TabIndex = 1; + labelFileName.Text = "Файл"; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(10, 61); + label1.Name = "label1"; + label1.Size = new Size(35, 15); + label1.TabIndex = 2; + label1.Text = "Дата:"; + // + // dateTimePicker + // + dateTimePicker.Location = new Point(157, 57); + dateTimePicker.Margin = new Padding(3, 2, 3, 2); + dateTimePicker.Name = "dateTimePicker"; + dateTimePicker.Size = new Size(161, 23); + dateTimePicker.TabIndex = 3; + // + // buttonCreate + // + buttonCreate.BackColor = Color.FromArgb(192, 255, 192); + buttonCreate.Location = new Point(10, 110); + buttonCreate.Margin = new Padding(3, 2, 3, 2); + buttonCreate.Name = "buttonCreate"; + buttonCreate.Size = new Size(306, 22); + buttonCreate.TabIndex = 4; + buttonCreate.Text = "Сформировать"; + buttonCreate.UseVisualStyleBackColor = false; + buttonCreate.Click += ButtonCreate_Click; + // + // FormDistribtionReport + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(346, 170); + Controls.Add(buttonCreate); + Controls.Add(dateTimePicker); + Controls.Add(label1); + Controls.Add(labelFileName); + Controls.Add(buttonSelectFileName); + Margin = new Padding(3, 2, 3, 2); + Name = "FormDistribtionReport"; + Text = "FormInvoiceDistributionReport"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button buttonSelectFileName; + private Label labelFileName; + private Label label1; + private DateTimePicker dateTimePicker; + private Button buttonCreate; + } +} \ No newline at end of file diff --git a/ShoeStore/Forms/FormDistributionReport.cs b/ShoeStore/Forms/FormDistributionReport.cs new file mode 100644 index 0000000..7dbfcbd --- /dev/null +++ b/ShoeStore/Forms/FormDistributionReport.cs @@ -0,0 +1,66 @@ +using ShoeStore.Reports; +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 Unity; + +namespace ShoeStore.Forms +{ + public partial class FormDistributionReport : Form + { + private string _fileName = string.Empty; + + private readonly IUnityContainer _container; + public FormDistributionReport(IUnityContainer container) + { + InitializeComponent(); + _container = container ?? throw new ArgumentNullException(nameof(container)); + } + + private void ButtonSelectFileName_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); + } + } + + private void ButtonCreate_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(_fileName)) + { + throw new Exception("Отсутствует имя файла для отчета"); + } + if + (_container.Resolve().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); + } + } + + } +} diff --git a/ShoeStore/Forms/FormDistributionReport.resx b/ShoeStore/Forms/FormDistributionReport.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/ShoeStore/Forms/FormDistributionReport.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ShoeStore/Forms/FormProductReport.Designer.cs b/ShoeStore/Forms/FormProductReport.Designer.cs new file mode 100644 index 0000000..1911397 --- /dev/null +++ b/ShoeStore/Forms/FormProductReport.Designer.cs @@ -0,0 +1,148 @@ +namespace ShoeStore.Forms +{ + partial class FormProductReport + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + label1 = new Label(); + label3 = new Label(); + label4 = new Label(); + textBoxFilePath = new TextBox(); + dateTimePickerStartDate = new DateTimePicker(); + dateTimePickerEndDate = new DateTimePicker(); + buttonSelectFilePath = new Button(); + buttonMakeReport = new Button(); + SuspendLayout(); + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(19, 15); + label1.Name = "label1"; + label1.Size = new Size(90, 15); + label1.TabIndex = 0; + label1.Text = "Путь до файла:"; + // + // label3 + // + label3.AutoSize = true; + label3.Location = new Point(19, 54); + label3.Name = "label3"; + label3.Size = new Size(77, 15); + label3.TabIndex = 2; + label3.Text = "Дата начала:"; + // + // label4 + // + label4.AutoSize = true; + label4.Location = new Point(19, 93); + label4.Name = "label4"; + label4.Size = new Size(71, 15); + label4.TabIndex = 3; + label4.Text = "Дата конца:"; + // + // textBoxFilePath + // + textBoxFilePath.Location = new Point(164, 15); + textBoxFilePath.Margin = new Padding(3, 2, 3, 2); + textBoxFilePath.Name = "textBoxFilePath"; + textBoxFilePath.ReadOnly = true; + textBoxFilePath.Size = new Size(129, 23); + textBoxFilePath.TabIndex = 4; + // + // dateTimePickerStartDate + // + dateTimePickerStartDate.Location = new Point(164, 54); + dateTimePickerStartDate.Margin = new Padding(3, 2, 3, 2); + dateTimePickerStartDate.Name = "dateTimePickerStartDate"; + dateTimePickerStartDate.Size = new Size(159, 23); + dateTimePickerStartDate.TabIndex = 5; + // + // dateTimePickerEndDate + // + dateTimePickerEndDate.Location = new Point(164, 89); + dateTimePickerEndDate.Margin = new Padding(3, 2, 3, 2); + dateTimePickerEndDate.Name = "dateTimePickerEndDate"; + dateTimePickerEndDate.Size = new Size(159, 23); + dateTimePickerEndDate.TabIndex = 6; + // + // buttonSelectFilePath + // + buttonSelectFilePath.BackColor = Color.FromArgb(192, 192, 255); + buttonSelectFilePath.Location = new Point(298, 15); + buttonSelectFilePath.Margin = new Padding(3, 2, 3, 2); + buttonSelectFilePath.Name = "buttonSelectFilePath"; + buttonSelectFilePath.Size = new Size(24, 22); + buttonSelectFilePath.TabIndex = 7; + buttonSelectFilePath.Text = ".."; + buttonSelectFilePath.UseVisualStyleBackColor = false; + buttonSelectFilePath.Click += ButtonSelectFilePath_Click; + // + // buttonMakeReport + // + buttonMakeReport.BackColor = Color.FromArgb(192, 192, 255); + buttonMakeReport.Location = new Point(19, 135); + buttonMakeReport.Margin = new Padding(3, 2, 3, 2); + buttonMakeReport.Name = "buttonMakeReport"; + buttonMakeReport.Size = new Size(304, 22); + buttonMakeReport.TabIndex = 9; + buttonMakeReport.Text = "Сформировать"; + buttonMakeReport.UseVisualStyleBackColor = false; + buttonMakeReport.Click += ButtonMakeReport_Click; + // + // FormProductReport + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(358, 175); + Controls.Add(buttonMakeReport); + Controls.Add(buttonSelectFilePath); + Controls.Add(dateTimePickerEndDate); + Controls.Add(dateTimePickerStartDate); + Controls.Add(textBoxFilePath); + Controls.Add(label4); + Controls.Add(label3); + Controls.Add(label1); + Margin = new Padding(3, 2, 3, 2); + Name = "FormProductReport"; + Text = "FormProductReport"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Label label1; + private Label label3; + private Label label4; + private TextBox textBoxFilePath; + private DateTimePicker dateTimePickerStartDate; + private DateTimePicker dateTimePickerEndDate; + private Button buttonSelectFilePath; + private Button buttonMakeReport; + } +} \ No newline at end of file diff --git a/ShoeStore/Forms/FormProductReport.cs b/ShoeStore/Forms/FormProductReport.cs new file mode 100644 index 0000000..8a612c3 --- /dev/null +++ b/ShoeStore/Forms/FormProductReport.cs @@ -0,0 +1,66 @@ +using ShoeStore.Reports; +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 Unity; + +namespace ShoeStore.Forms +{ + public partial class FormProductReport : Form + { + IUnityContainer _container; + + public FormProductReport(IUnityContainer container) + { + InitializeComponent(); + _container = container ?? throw new ArgumentNullException(nameof(container)); + } + + private void ButtonSelectFilePath_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 ButtonMakeReport_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBoxFilePath.Text)) + { + throw new Exception("Отсутствует имя файла для отчета"); + } + if (dateTimePickerEndDate.Value <= dateTimePickerStartDate.Value) + { + throw new Exception("Дата начала должна быть раньше даты окончания"); + } + if (_container.Resolve().CreateTable(textBoxFilePath.Text, dateTimePickerStartDate.Value, dateTimePickerEndDate.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); + } + } + } +} diff --git a/ShoeStore/Forms/FormProductReport.resx b/ShoeStore/Forms/FormProductReport.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/ShoeStore/Forms/FormProductReport.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ShoeStore/Forms/FormProducts.cs b/ShoeStore/Forms/FormProducts.cs index d857df6..f282cb1 100644 --- a/ShoeStore/Forms/FormProducts.cs +++ b/ShoeStore/Forms/FormProducts.cs @@ -102,7 +102,7 @@ namespace ShoeStore.Forms { try { - //_container.Resolve().ShowDialog(); + //_container.Resolve().ShowDialog(); LoadList(); } catch (Exception ex) diff --git a/ShoeStore/Forms/FormReceipt.Designer.cs b/ShoeStore/Forms/FormReceipt.Designer.cs index 223f3d9..33d09c8 100644 --- a/ShoeStore/Forms/FormReceipt.Designer.cs +++ b/ShoeStore/Forms/FormReceipt.Designer.cs @@ -36,6 +36,8 @@ comboBoxProdctType = new ComboBox(); label1 = new Label(); dateTimePickerDate = new DateTimePicker(); + label2 = new Label(); + comboBoxProduct = new ComboBox(); ((System.ComponentModel.ISupportInitialize)numericUpDownNumOfPairs).BeginInit(); SuspendLayout(); // @@ -57,7 +59,7 @@ // // buttonCancel // - buttonCancel.Location = new Point(258, 255); + buttonCancel.Location = new Point(246, 307); buttonCancel.Name = "buttonCancel"; buttonCancel.Size = new Size(102, 23); buttonCancel.TabIndex = 18; @@ -67,7 +69,7 @@ // // buttonSave // - buttonSave.Location = new Point(58, 255); + buttonSave.Location = new Point(46, 307); buttonSave.Name = "buttonSave"; buttonSave.Size = new Size(100, 23); buttonSave.TabIndex = 17; @@ -108,11 +110,30 @@ dateTimePickerDate.Size = new Size(132, 23); dateTimePickerDate.TabIndex = 21; // + // label2 + // + label2.AutoSize = true; + label2.Location = new Point(27, 223); + label2.Name = "label2"; + label2.Size = new Size(56, 15); + label2.TabIndex = 23; + label2.Text = "Продукт:"; + // + // comboBoxProduct + // + comboBoxProduct.FormattingEnabled = true; + comboBoxProduct.Location = new Point(246, 220); + comboBoxProduct.Name = "comboBoxProduct"; + comboBoxProduct.Size = new Size(121, 23); + comboBoxProduct.TabIndex = 24; + // // FormReceipt // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(398, 330); + ClientSize = new Size(398, 369); + Controls.Add(comboBoxProduct); + Controls.Add(label2); Controls.Add(label1); Controls.Add(dateTimePickerDate); Controls.Add(comboBoxProdctType); @@ -137,5 +158,7 @@ private ComboBox comboBoxProdctType; private Label label1; private DateTimePicker dateTimePickerDate; + private Label label2; + private ComboBox comboBoxProduct; } } \ No newline at end of file diff --git a/ShoeStore/Forms/FormReceipt.cs b/ShoeStore/Forms/FormReceipt.cs index 6ec87f4..e5536b2 100644 --- a/ShoeStore/Forms/FormReceipt.cs +++ b/ShoeStore/Forms/FormReceipt.cs @@ -20,7 +20,7 @@ namespace ShoeStore.Froms //private int? _receiptId; - public FormReceipt(IReceiptRepository receiptRepository) + public FormReceipt(IReceiptRepository receiptRepository, IProductRepository productRepository) { InitializeComponent(); _receiptRepository = receiptRepository ?? throw new ArgumentNullException(nameof(receiptRepository)); @@ -30,6 +30,10 @@ namespace ShoeStore.Froms comboBoxProdctType.Items.Add(elem); } + comboBoxProduct.DataSource = productRepository.ReadProducts(); + comboBoxProduct.DisplayMember = "NameOfShoes"; + comboBoxProduct.ValueMember = "Id"; + } private void buttonSave_Click(object sender, EventArgs e) @@ -45,7 +49,7 @@ namespace ShoeStore.Froms { throw new Exception("Не выбран тип продукта"); } - if (numericUpDownNumOfPairs.Value < 0) + if (numericUpDownNumOfPairs.Value < 0 || comboBoxProduct.SelectedIndex < 0) { throw new Exception("Имеются незаполненные поля"); } @@ -53,7 +57,8 @@ namespace ShoeStore.Froms 0, productType, dateTimePickerDate.Value, - Convert.ToInt32(numericUpDownNumOfPairs.Value))); + Convert.ToInt32(numericUpDownNumOfPairs.Value), + (int)comboBoxProduct.SelectedValue!)); Close(); } diff --git a/ShoeStore/Forms/FormSale.cs b/ShoeStore/Forms/FormSale.cs index c6d8627..14a5517 100644 --- a/ShoeStore/Forms/FormSale.cs +++ b/ShoeStore/Forms/FormSale.cs @@ -40,7 +40,7 @@ public partial class FormSale : Form } - _saleRepository.CreateSale(Sale.CreateOperation(0, Convert.ToInt32(numericUpDownStorageSize.Value), dateTimePickerDate.Value, CreateListProductSaleFromDataGrid())); + _saleRepository.CreateSale(Sale.CreateOperation(0, dateTimePickerDate.Value, CreateListProductSaleFromDataGrid())); MessageBox.Show("Данные успешно добавлены!", "Информация", MessageBoxButtons.OK, MessageBoxIcon.Information); Close(); diff --git a/ShoeStore/Reports/ChartReport.cs b/ShoeStore/Reports/ChartReport.cs new file mode 100644 index 0000000..3134b25 --- /dev/null +++ b/ShoeStore/Reports/ChartReport.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.Logging; +using ShoeStore.Repositories; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShoeStore.Reports; + +public class ChartReport +{ + private readonly IReceiptRepository _receiptRepository; + private readonly ILogger _logger; + public ChartReport(IReceiptRepository receiptRepository, ILogger logger) + { + _receiptRepository = receiptRepository ?? throw new ArgumentNullException(nameof(receiptRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + public bool CreateChart(string filePath, DateTime dateTime) + { + try + { + new PdfBuilder(filePath) + .AddHeader("Количество поступивших товаров") + .AddPieChart("Товары", GetData(dateTime)) + .Build(); + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка при формировании документа"); + return false; + } + } + + private List<(string Caption, double Value)> GetData(DateTime dateTime) + { + return _receiptRepository + .ReadReceipts() + .Where(x => x.DateOfReceipt.Date == dateTime.Date) + .GroupBy(x => x.ProductId, (key, group) => new { ID = key, Count = group.Sum(y => y.NumberOfPairsReceived) }) + .Select(x => (x.ID.ToString(), (double)x.Count)) + .ToList(); + } +} diff --git a/ShoeStore/Reports/PdfBuilder.cs b/ShoeStore/Reports/PdfBuilder.cs new file mode 100644 index 0000000..12ab590 --- /dev/null +++ b/ShoeStore/Reports/PdfBuilder.cs @@ -0,0 +1,87 @@ +using MigraDoc.DocumentObjectModel; +using MigraDoc.DocumentObjectModel.Shapes.Charts; +using MigraDoc.Rendering; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShoeStore.Reports; + +public 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.AddStyle("NormalBold", "Normal"); + headerStyle.Font.Bold = true; + headerStyle.Font.Size = 14; + } +} diff --git a/ShoeStore/Reports/TableReport.cs b/ShoeStore/Reports/TableReport.cs index fbef593..d5ed765 100644 --- a/ShoeStore/Reports/TableReport.cs +++ b/ShoeStore/Reports/TableReport.cs @@ -24,14 +24,13 @@ internal class TableReport _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - public bool CreateTable(string filePath, int productID, DateTime startDate, DateTime endDate) + public bool CreateTable(string filePath, DateTime startDate, DateTime endDate) { - try - + try { new ExcelBuilder(filePath) .AddHeader("Сводка по движению товара", 0, 4) .AddParagraph("за период", 0) - .AddTable([10, 10, 15, 15], GetData(productID, startDate, endDate)) + .AddTable([10, 10, 15, 15], GetData(startDate, endDate)) .Build(); return true; } @@ -42,23 +41,23 @@ internal class TableReport } } - private List GetData(int productID, DateTime startDate, DateTime endDate) + private List GetData(DateTime startDate, DateTime endDate) { var data = _saleRepository .ReadSales() - .Where(x => x.DateOfSale >= startDate && x.DateOfSale <= endDate && x..Any(y => y.ProductID == productID)) - .Select(x => new { x.Products.First(y => y.ProductID == productID).ProductID, Date = x.DateOfReceipt, CountIn = (int?)null, CountOut = (int?)x.Products.FirstOrDefault(y => y.ProductID == productID)?.Count }) + .Where(x => x.DateOfSale >= startDate && x.DateOfSale <= endDate && x.Product.Any(y => y.SaleId == x.Id)) + .Select(x => new { x.Product.First(y => y.SaleId == x.Id).ProductId, Date = x.DateOfSale, CountIn = (int?)null, CountOut = (int?)x.Product.FirstOrDefault(y => y.SaleId == x.Id)?.SalesNumber }) .Union( - _saleRepository - .ReadSales() - .Where(x => x.DateOfSale >= startDate && x.DateOfSale <= endDate && x.ProductID == productID && x.MovementType == Movement.Reseipt) - .Select(x => new { x.ProductID, x.Date, CountIn = (int?)x.Count, CountOut = (int?)null })) + _receiptRepository + .ReadReceipts() + .Where(x => x.DateOfReceipt >= startDate && x.DateOfReceipt <= endDate) + .Select(x => new { x.ProductId, Date = x.DateOfReceipt, CountIn = (int?)x.NumberOfPairsReceived, CountOut = (int?)null })) .OrderBy(x => x.Date); return new List() { item } .Union( data - .Select(x => new string[] { x.ProductID.ToString(), x.Date.ToString(), x.CountIn?.ToString() ?? string.Empty, x.CountOut?.ToString() ?? string.Empty })) + .Select(x => new string[] { x.ProductId.ToString(), x.Date.ToString(), x.CountIn?.ToString() ?? string.Empty, x.CountOut?.ToString() ?? string.Empty })) .Union([["Всего", "", data.Sum(x => x.CountIn ?? 0).ToString(), data.Sum(x => x.CountOut ?? 0).ToString()]]) .ToList(); diff --git a/ShoeStore/Repositories/Implementations/ConnectionString.cs b/ShoeStore/Repositories/Implementations/ConnectionString.cs index d202538..f805811 100644 --- a/ShoeStore/Repositories/Implementations/ConnectionString.cs +++ b/ShoeStore/Repositories/Implementations/ConnectionString.cs @@ -8,6 +8,6 @@ namespace ShoeStore.Repositories.Implementations; internal class ConnectionString : IConnectionString { - string IConnectionString.ConnectionString => "Server=127.0.0.1;Port=5432;Database=shoestore_oop;Uid=postgres;Pwd=01010101;"; + string IConnectionString.ConnectionString => "Server=127.0.0.1;Port=5432;Database=shoestore_otp;Uid=postgres;Pwd=01010101;"; } \ No newline at end of file diff --git a/ShoeStore/Repositories/Implementations/EmployeeRepository.cs b/ShoeStore/Repositories/Implementations/EmployeeRepository.cs index da36d62..fa2e409 100644 --- a/ShoeStore/Repositories/Implementations/EmployeeRepository.cs +++ b/ShoeStore/Repositories/Implementations/EmployeeRepository.cs @@ -28,8 +28,8 @@ public class EmployeeRepository : IEmployeeRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryInsert = @"INSERT INTO Employees (NumberStorage, StorageSize, Date) - VALUES (@NumberStorage, @StorageSize, @Date)"; + var queryInsert = @"INSERT INTO Employee (NumberStorage, Date) + VALUES (@NumberStorage, @Date)"; connection.Execute(queryInsert, employee); } catch (Exception ex) @@ -46,7 +46,7 @@ public class EmployeeRepository : IEmployeeRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryDelete = @"DELETE FROM Employees WHERE ID=@id"; + var queryDelete = @"DELETE FROM Employee WHERE ID=@id"; connection.Execute(queryDelete, new { id }); } catch (Exception ex) @@ -63,7 +63,7 @@ public class EmployeeRepository : IEmployeeRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = @"SELECT * FROM Employees WHERE ID=@id"; + var querySelect = @"SELECT * FROM Employee WHERE ID=@id"; var employee = connection.QueryFirst(querySelect, new { id @@ -85,7 +85,7 @@ public IEnumerable ReadEmployees() try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = "SELECT * FROM Employees"; + var querySelect = "SELECT * FROM Employee"; var employee = connection.Query(querySelect); _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(employee)); @@ -106,7 +106,7 @@ public IEnumerable ReadEmployees() try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryUpdate = @"UPDATE Employees SET + var queryUpdate = @"UPDATE Employee SET NumberStorage=@NumberStorage, StorageSize=@StorageSize, Date=@Date diff --git a/ShoeStore/Repositories/Implementations/ProductRepository.cs b/ShoeStore/Repositories/Implementations/ProductRepository.cs index f155bfc..5395ec9 100644 --- a/ShoeStore/Repositories/Implementations/ProductRepository.cs +++ b/ShoeStore/Repositories/Implementations/ProductRepository.cs @@ -37,23 +37,10 @@ public class ProductRepository : IProductRepository { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); connection.Open(); - using var transaction = connection.BeginTransaction(); var queryInsert = @"INSERT INTO Product (Nameofshoes, manufacturingcompany, price) VALUES (@Nameofshoes, @manufacturingcompany, @price); SELECT MAX(Id) FROM Product"; - var ProductID = connection.QueryFirst(queryInsert, product, transaction); - var querySubInsert = @"INSERT INTO Product_Sales (ID, Amount, SalesNumber) - VALUES (@ID, @Amount, @SalesNumber)"; - foreach (var elem in product.Sales) - { - connection.Execute(querySubInsert, new - { - ProductID, - elem.SaleId, - elem.SalesNumber - }, transaction); - } - transaction.Commit(); + connection.Execute(queryInsert, product); } catch (Exception ex) { diff --git a/ShoeStore/Repositories/Implementations/ReceiptRepository.cs b/ShoeStore/Repositories/Implementations/ReceiptRepository.cs index 619501b..8ab6f4a 100644 --- a/ShoeStore/Repositories/Implementations/ReceiptRepository.cs +++ b/ShoeStore/Repositories/Implementations/ReceiptRepository.cs @@ -33,8 +33,8 @@ public class ReceiptRepository : IReceiptRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryInsert = @"INSERT INTO Receipts (ProductType, NumberOfPairsReceived, DateOfReceipt) - VALUES (@ProductType, @NumberOfPairsReceived, @DateOfReceipt)"; + var queryInsert = @"INSERT INTO Receipt (ProductType, NumberOfPairsReceived, DateOfReceipt, ProductId) + VALUES (@ProductType, @NumberOfPairsReceived, @DateOfReceipt, @ProductId)"; connection.Execute(queryInsert, receipt); } catch (Exception ex) @@ -50,7 +50,7 @@ public class ReceiptRepository : IReceiptRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = "SELECT * FROM Receipts"; + var querySelect = "SELECT * FROM Receipt"; var receipt = connection.Query(querySelect); _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(receipt)); diff --git a/ShoeStore/Repositories/Implementations/SaleRepository.cs b/ShoeStore/Repositories/Implementations/SaleRepository.cs index 87db365..2b1b931 100644 --- a/ShoeStore/Repositories/Implementations/SaleRepository.cs +++ b/ShoeStore/Repositories/Implementations/SaleRepository.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Unity; namespace ShoeStore.Repositories.Implementations; @@ -35,19 +36,19 @@ public class SaleRepository : ISaleRepository connection.Open(); using var transaction = connection.BeginTransaction(); var queryInsert = @" - INSERT INTO Sales (SalesNumber, DateOfSale) - VALUES (@SalesNumber, @DateOfSale); - SELECT MAX(Id) FROM Sales"; + INSERT INTO Sale (DateOfSale) + VALUES (@DateOfSale); + SELECT MAX(Id) FROM Sale"; var visitingId = connection.QueryFirst(queryInsert, sale, transaction); var querySubInsert = @" - INSERT INTO Product_Sales (Amount, SalesNumber) - VALUES (@Amount,@SalesNumber)"; + INSERT INTO ProductSale (ProductId, SaleId, SalesNumber) + VALUES (@ProductId, @visitingId, @SalesNumber)"; foreach (var elem in sale.Product) { connection.Execute(querySubInsert, new { elem.ProductId, - elem.SaleId, + visitingId, elem.SalesNumber }, transaction); } @@ -67,7 +68,7 @@ public class SaleRepository : ISaleRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryDelete = @"DELETE FROM Sales + var queryDelete = @"DELETE FROM Sale WHERE ID=@id"; connection.Execute(queryDelete, new { id }); } @@ -85,12 +86,15 @@ public class SaleRepository : ISaleRepository { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = @"SELECT * FROM Sales"; - var sale = - connection.Query(querySelect); + var querySelect = @"SELECT s.*, ps.ProductId, ps.SalesNumber + FROM Sale s + INNER JOIN ProductSale ps ON ps.SaleId = s.Id"; + var sale = connection.Query(querySelect); _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(sale)); - return sale; + return sale.GroupBy(x => x.Id, y => y, + (key, value) => Sale.CreateOperation(value.First(), + value.Select(z => ProductSale.CreateOperation( z.ProductId, z.Id, z.SalesNumber)))).ToList(); } catch (Exception ex) { diff --git a/ShoeStore/Repositories/Implementations/StorageRepository.cs b/ShoeStore/Repositories/Implementations/StorageRepository.cs index ed6af93..6fbf53f 100644 --- a/ShoeStore/Repositories/Implementations/StorageRepository.cs +++ b/ShoeStore/Repositories/Implementations/StorageRepository.cs @@ -30,7 +30,7 @@ public class StorageRepository : IStorageRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryInsert = @"INSERT INTO Storages (Size, NumberStorage, QuantityInStock) + var queryInsert = @"INSERT INTO Storage (Size, NumberStorage, QuantityInStock) VALUES (@Size, @NumberStorage, @QuantityInStock)"; connection.Execute(queryInsert, storage); } @@ -48,7 +48,7 @@ public class StorageRepository : IStorageRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryDelete = @"DELETE FROM Storages WHERE ID=@id"; + var queryDelete = @"DELETE FROM Storage WHERE ID=@id"; connection.Execute(queryDelete, new { id }); } catch (Exception ex) @@ -65,7 +65,7 @@ public class StorageRepository : IStorageRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = @"SELECT * FROM Storages WHERE ID=@id"; + var querySelect = @"SELECT * FROM Storage WHERE ID=@id"; var storage = connection.QueryFirst(querySelect, new { id @@ -87,7 +87,7 @@ public class StorageRepository : IStorageRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = "SELECT * FROM Storages"; + var querySelect = "SELECT * FROM Storage"; var storage = connection.Query(querySelect); _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(storage)); @@ -108,7 +108,7 @@ public class StorageRepository : IStorageRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var queryUpdate = @"UPDATE Storages SET + var queryUpdate = @"UPDATE Storage SET Size=@Size, NumberStorage=@NumberStorage, QuantityInStock=@QuantityInStock diff --git a/ShoeStore/ShoeStore.Designer.cs b/ShoeStore/ShoeStore.Designer.cs index c67bda4..8c978a5 100644 --- a/ShoeStore/ShoeStore.Designer.cs +++ b/ShoeStore/ShoeStore.Designer.cs @@ -38,6 +38,8 @@ SalesToolStripMenuItem = new ToolStripMenuItem(); отчетыToolStripMenuItem = new ToolStripMenuItem(); DirectoryReportToolStripMenuItem = new ToolStripMenuItem(); + ProductReportToolStripMenuItem = new ToolStripMenuItem(); + ProductDistributionToolStripMenuItem = new ToolStripMenuItem(); menuStrip1.SuspendLayout(); SuspendLayout(); // @@ -101,7 +103,7 @@ // // отчетыToolStripMenuItem // - отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { DirectoryReportToolStripMenuItem }); + отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { DirectoryReportToolStripMenuItem, ProductReportToolStripMenuItem, ProductDistributionToolStripMenuItem }); отчетыToolStripMenuItem.Name = "отчетыToolStripMenuItem"; отчетыToolStripMenuItem.Size = new Size(60, 20); отчетыToolStripMenuItem.Text = "Отчеты"; @@ -114,12 +116,25 @@ DirectoryReportToolStripMenuItem.Text = "Документ со справониками"; DirectoryReportToolStripMenuItem.Click += DirectoryReportToolStripMenuItem_Click; // + // ProductReportToolStripMenuItem + // + ProductReportToolStripMenuItem.Name = "ProductReportToolStripMenuItem"; + ProductReportToolStripMenuItem.Size = new Size(273, 22); + ProductReportToolStripMenuItem.Text = "Движение товаров"; + ProductReportToolStripMenuItem.Click += ProductReportToolStripMenuItem_Click; + // + // ProductDistributionToolStripMenuItem + // + ProductDistributionToolStripMenuItem.Name = "ProductDistributionToolStripMenuItem"; + ProductDistributionToolStripMenuItem.Size = new Size(273, 22); + ProductDistributionToolStripMenuItem.Text = "Поступившие товары"; + ProductDistributionToolStripMenuItem.Click += ProductDistributionToolStripMenuItem_Click; + // // ShoeStore // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; BackColor = SystemColors.ControlLightLight; - BackgroundImage = Properties.Resources.обувной; BackgroundImageLayout = ImageLayout.Zoom; ClientSize = new Size(800, 450); Controls.Add(menuStrip1); @@ -144,5 +159,7 @@ private ToolStripMenuItem SalesToolStripMenuItem; private ToolStripMenuItem отчетыToolStripMenuItem; private ToolStripMenuItem DirectoryReportToolStripMenuItem; + private ToolStripMenuItem ProductReportToolStripMenuItem; + private ToolStripMenuItem ProductDistributionToolStripMenuItem; } } \ No newline at end of file diff --git a/ShoeStore/ShoeStore.cs b/ShoeStore/ShoeStore.cs index 2c54511..cfd94ef 100644 --- a/ShoeStore/ShoeStore.cs +++ b/ShoeStore/ShoeStore.cs @@ -95,5 +95,29 @@ namespace ShoeStore MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error); } } + + private void ProductReportToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + _container.Resolve().ShowDialog(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ProductDistributionToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + _container.Resolve().ShowDialog(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка при загрузке", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } } } diff --git a/ShoeStore/ShoeStore.csproj b/ShoeStore/ShoeStore.csproj index 62b2a29..f9436c8 100644 --- a/ShoeStore/ShoeStore.csproj +++ b/ShoeStore/ShoeStore.csproj @@ -16,6 +16,7 @@ +