From 208f744ef564065e4bc30f88fde7d45d1963b07c Mon Sep 17 00:00:00 2001 From: vettaql Date: Tue, 24 Dec 2024 01:32:15 +0400 Subject: [PATCH] lab4 --- Atelier/Atelier/Entities/Client.cs | 10 +- Atelier/Atelier/Entities/Fabric.cs | 11 +- Atelier/Atelier/Entities/FabricModel.cs | 1 + Atelier/Atelier/Entities/Model.cs | 9 + Atelier/Atelier/Entities/ModelOrder.cs | 1 + Atelier/Atelier/Entities/Order.cs | 26 +- Atelier/Atelier/Entities/Storage.cs | 10 +- Atelier/Atelier/Forms/FormClients.cs | 8 +- Atelier/Atelier/Forms/FormFabrics.cs | 8 +- Atelier/Atelier/Forms/FormModels.cs | 8 +- Atelier/Atelier/Forms/FormOrder.cs | 2 +- Atelier/Atelier/Forms/FormOrders.cs | 8 +- Atelier/Atelier/Forms/FormStorages.cs | 9 +- Atelier/Atelier/Reports/ChartReport.cs | 7 +- Atelier/Atelier/Reports/ExcelBuilder.cs | 573 +++++++++--------- Atelier/Atelier/Reports/TableReport.cs | 44 +- .../Repositories/IStorageRepository.cs | 2 +- .../Implementations/ModelRepository.cs | 12 +- .../Implementations/OrderRepository.cs | 125 ++-- .../Implementations/StorageRepository.cs | 75 ++- 20 files changed, 569 insertions(+), 380 deletions(-) diff --git a/Atelier/Atelier/Entities/Client.cs b/Atelier/Atelier/Entities/Client.cs index d981a91..dfdf65c 100644 --- a/Atelier/Atelier/Entities/Client.cs +++ b/Atelier/Atelier/Entities/Client.cs @@ -1,8 +1,16 @@ -public class Client +using System.ComponentModel; + +public class Client { 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 string ContactInformation { get; private set; } = string.Empty; public static Client CreateEntity(int id, string firstName, string lastName, string contactInformation) diff --git a/Atelier/Atelier/Entities/Fabric.cs b/Atelier/Atelier/Entities/Fabric.cs index fb6e783..5d8e078 100644 --- a/Atelier/Atelier/Entities/Fabric.cs +++ b/Atelier/Atelier/Entities/Fabric.cs @@ -1,8 +1,13 @@ -public class Fabric +using System.ComponentModel; + +public class Fabric { public int Id { get; private set; } - public FabricType FabricType { get; private set; } - public Color Color { get; private set; } + [DisplayName("Тип ткани")] + public FabricType FabricType { get; private set; } + [DisplayName("Цвет")] + public Color Color { get; private set; } + [DisplayName("Метраж")] public double Metrage { get; private set; } public static Fabric CreateEntity(int id, FabricType fabricType, Color color, double metrage) { diff --git a/Atelier/Atelier/Entities/FabricModel.cs b/Atelier/Atelier/Entities/FabricModel.cs index 442ad77..b94a0d3 100644 --- a/Atelier/Atelier/Entities/FabricModel.cs +++ b/Atelier/Atelier/Entities/FabricModel.cs @@ -3,6 +3,7 @@ public int FabricId { get; private set; } public int ModelId { get; private set; } public int Count { get; private set; } + public string FabricName { get; private set; } = string.Empty; public static FabricModel CreateElement(int fabricId, int modelId, int count) { return new FabricModel diff --git a/Atelier/Atelier/Entities/Model.cs b/Atelier/Atelier/Entities/Model.cs index 89e294b..853e082 100644 --- a/Atelier/Atelier/Entities/Model.cs +++ b/Atelier/Atelier/Entities/Model.cs @@ -1,10 +1,19 @@ using Microsoft.VisualBasic.FileIO; +using System.ComponentModel; public class Model { public int Id { get; private set; } + [DisplayName("Модель")] public ModelType ModelType { get; private set; } + [DisplayName("Цена")] public double Price { get; private set; } + + [DisplayName("Ткань")] + public string Fabric => FabricModel != null ? + string.Join(", ", FabricModel.Select(x => $"{x.FabricName} {x.Count}")) : string.Empty; + + [Browsable(false)] public IEnumerable FabricModel { get;private set;} = []; public static Model CreateEntity(int id, ModelType modelType,double price, IEnumerable fabricModel) diff --git a/Atelier/Atelier/Entities/ModelOrder.cs b/Atelier/Atelier/Entities/ModelOrder.cs index d409dde..595c3c1 100644 --- a/Atelier/Atelier/Entities/ModelOrder.cs +++ b/Atelier/Atelier/Entities/ModelOrder.cs @@ -3,6 +3,7 @@ public int OrderId { get; private set; } public int ModelId { get; private set; } public int Count { get; private set; } + public string ModelName { get; private set; } = string.Empty; public static ModelOrder CreateElement(int orderId, int modelId, int count) { return new ModelOrder diff --git a/Atelier/Atelier/Entities/Order.cs b/Atelier/Atelier/Entities/Order.cs index 8c8a71a..85c9656 100644 --- a/Atelier/Atelier/Entities/Order.cs +++ b/Atelier/Atelier/Entities/Order.cs @@ -1,9 +1,23 @@ -public class Order +using System.ComponentModel; + +public class Order { public int Id { get; private set; } - public DateTime Date { get; private set; } + [DisplayName("Дата")] + public DateTime Date { get; private set; } + [DisplayName("Статус")] public Status Status { get; private set; } + [Browsable(false)] + public int ClientId { get; private set; } + [DisplayName("Клиент")] + public string ClientName { get; private set; } = string.Empty; + + [DisplayName("Модель")] + public string Model => ModelOrder != null ? + string.Join(", ", ModelOrder.Select(x => $"{x.ModelName} {x.Count}")) :string.Empty; + + [Browsable(false)] public IEnumerable ModelOrder { get; private set; } = []; public static Order CreateOperation(int id,DateTime date, Status status, int clientId, IEnumerable modelOrder) @@ -18,5 +32,11 @@ }; } - + public void SetModelOrder(IEnumerable modelOrders) + { + if (modelOrders != null && modelOrders.Any()) + { + ModelOrder = modelOrders; + } + } } \ No newline at end of file diff --git a/Atelier/Atelier/Entities/Storage.cs b/Atelier/Atelier/Entities/Storage.cs index d9ca4e6..12cfc94 100644 --- a/Atelier/Atelier/Entities/Storage.cs +++ b/Atelier/Atelier/Entities/Storage.cs @@ -1,8 +1,16 @@ -public class Storage +using System.ComponentModel; + +public class Storage { public int Id { get; private set; } + [Browsable(false)] public int FabricId { get; private set; } + [DisplayName("Ткань")] + public string FabricName { get; private set; } = string.Empty; + + [DisplayName("Метраж")] public double StockMetrage { get; private set; } + [DisplayName("Дата")] public DateTime DateStorage { get; private set; } public static Storage CreateOperation(int id, int fabricId, double stockMetrage, DateTime dateStorage) diff --git a/Atelier/Atelier/Forms/FormClients.cs b/Atelier/Atelier/Forms/FormClients.cs index 775a98c..c97b1d1 100644 --- a/Atelier/Atelier/Forms/FormClients.cs +++ b/Atelier/Atelier/Forms/FormClients.cs @@ -92,7 +92,13 @@ namespace Atelier.Forms MessageBoxButtons.OK, MessageBoxIcon.Error); } } - private void LoadList() => dataGridView1.DataSource = _clientRepository.ReadClients(); + private void LoadList() + { + dataGridView1.DataSource = _clientRepository.ReadClients(); + dataGridView1.Columns["Id"].Visible = false; + dataGridView1.Columns["FullName"].Visible = false; + + } private bool TryGetIdentifierFromSelectedRow(out int id) { id = 0; diff --git a/Atelier/Atelier/Forms/FormFabrics.cs b/Atelier/Atelier/Forms/FormFabrics.cs index aefec2d..87f02ae 100644 --- a/Atelier/Atelier/Forms/FormFabrics.cs +++ b/Atelier/Atelier/Forms/FormFabrics.cs @@ -90,7 +90,13 @@ namespace Atelier.Forms MessageBoxButtons.OK, MessageBoxIcon.Error); } } - private void LoadList() => dataGridView1.DataSource = _fabricRepository.ReadFabrics(); + private void LoadList() + + { + dataGridView1.DataSource = _fabricRepository.ReadFabrics(); + dataGridView1.Columns["Id"].Visible = false; + + } private bool TryGetIdentifierFromSelectedRow(out int id) { id = 0; diff --git a/Atelier/Atelier/Forms/FormModels.cs b/Atelier/Atelier/Forms/FormModels.cs index 1d9d3d1..a8ee51b 100644 --- a/Atelier/Atelier/Forms/FormModels.cs +++ b/Atelier/Atelier/Forms/FormModels.cs @@ -91,7 +91,13 @@ namespace Atelier.Forms MessageBoxButtons.OK, MessageBoxIcon.Error); } } - private void LoadList() => dataGridView1.DataSource = _modelRepository.ReadModels(); + private void LoadList() + + { + dataGridView1.DataSource = _modelRepository.ReadModels(); + dataGridView1.Columns["Id"].Visible = false; + + } private bool TryGetIdentifierFromSelectedRow(out int id) { id = 0; diff --git a/Atelier/Atelier/Forms/FormOrder.cs b/Atelier/Atelier/Forms/FormOrder.cs index a217612..9694f57 100644 --- a/Atelier/Atelier/Forms/FormOrder.cs +++ b/Atelier/Atelier/Forms/FormOrder.cs @@ -21,7 +21,7 @@ namespace Atelier.Forms throw new ArgumentNullException(nameof(orderRepository)); comboBoxClient.DataSource = clientRepository.ReadClients(); - comboBoxClient.DisplayMember = "FirstName"; + comboBoxClient.DisplayMember = "FullName"; comboBoxClient.ValueMember = "Id"; comboBoxStatus.DataSource = orderRepository.ReadOrders(); comboBoxStatus.DataSource = Enum.GetValues(typeof(Status)); diff --git a/Atelier/Atelier/Forms/FormOrders.cs b/Atelier/Atelier/Forms/FormOrders.cs index bc9fb9e..48daf1a 100644 --- a/Atelier/Atelier/Forms/FormOrders.cs +++ b/Atelier/Atelier/Forms/FormOrders.cs @@ -73,7 +73,13 @@ namespace Atelier.Forms MessageBoxButtons.OK, MessageBoxIcon.Error); } } - private void LoadList() => dataGridView1.DataSource = _orderRepository.ReadOrders(); + private void LoadList() + { + dataGridView1.DataSource = _orderRepository.ReadOrders(); + dataGridView1.Columns["Id"].Visible = false; + dataGridView1.Columns["Date"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm"; + } + private bool TryGetIdentifierFromSelectedRow(out int id) { id = 0; diff --git a/Atelier/Atelier/Forms/FormStorages.cs b/Atelier/Atelier/Forms/FormStorages.cs index 57df5e5..0b55873 100644 --- a/Atelier/Atelier/Forms/FormStorages.cs +++ b/Atelier/Atelier/Forms/FormStorages.cs @@ -72,8 +72,13 @@ namespace Atelier.Forms MessageBoxButtons.OK, MessageBoxIcon.Error); } } - private void LoadList() => dataGridView1.DataSource = - _storageRepository.ReadStorage(); + private void LoadList() + { + dataGridView1.DataSource = _storageRepository.ReadStorage(); + dataGridView1.Columns["Id"].Visible = false; + dataGridView1.Columns["DateStorage"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm"; + } + private bool TryGetIdentifierFromSelectedRow(out int id) { id = 0; diff --git a/Atelier/Atelier/Reports/ChartReport.cs b/Atelier/Atelier/Reports/ChartReport.cs index f4d9167..dbfcd14 100644 --- a/Atelier/Atelier/Reports/ChartReport.cs +++ b/Atelier/Atelier/Reports/ChartReport.cs @@ -22,11 +22,11 @@ namespace Atelier.Reports try { var data = GetData(dateTime); - _logger.LogDebug("Data for chart: {Data}", System.Text.Json.JsonSerializer.Serialize(data)); + _logger.LogDebug("Data for chart: {Data}", JsonSerializer.Serialize(data)); new PdfBuilder(filePath) - .AddHeader("Склад тканей") - .AddPieChart("Остатки тканей", data) + .AddHeader("Склад") + .AddPieChart($"Остатки на {dateTime:dd MMMM yyyy}", data) .Build(); return true; } @@ -49,6 +49,5 @@ namespace Atelier.Reports _logger.LogDebug("Raw data: {Data}", JsonSerializer.Serialize(data)); return data; } - } } diff --git a/Atelier/Atelier/Reports/ExcelBuilder.cs b/Atelier/Atelier/Reports/ExcelBuilder.cs index 0511dc5..8d1ba4c 100644 --- a/Atelier/Atelier/Reports/ExcelBuilder.cs +++ b/Atelier/Atelier/Reports/ExcelBuilder.cs @@ -7,304 +7,309 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Atelier.Reports; - -public class ExcelBuilder +namespace Atelier.Reports { - private readonly string _filePath; - private readonly SheetData _sheetData; - private readonly MergeCells _mergeCells; - private readonly Columns _columns; - private uint _rowIndex = 0; + public 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)) + public ExcelBuilder(string 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 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) + if (string.IsNullOrWhiteSpace(filePath)) { - CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder); + 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); + _mergeCells.Append(new MergeCell() + { + Reference = new StringValue($"{GetExcelColumnName(columnIndex)}{_rowIndex}:{GetExcelColumnName(columnIndex + 1)}{_rowIndex}") + }); + _rowIndex++; + return this; + } + + public ExcelBuilder AddTable(int[] columnsWidths, List 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 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.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().First()); - } - } - - private static void GenerateStyle(WorkbookPart workbookPart) - { - var workbookStylesPart = workbookPart.AddNewPart(); - 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() + for (var i = 1; i < data.Count - 1; ++i) { - Val = new EnumValue(FontSchemeValues.Minor) - } - }); - - fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font - { - FontSize = new FontSize() { Val = 11 }, - FontName = new FontName() { Val = "Calibri" }, - Bold = new Bold(), - FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 }, - FontScheme = new FontScheme() - { - Val = new EnumValue(FontSchemeValues.Minor) - } - }); - workbookStylesPart.Stylesheet.Append(fonts); - // Default Fill - var fills = new Fills() { Count = 1 }; - fills.Append(new Fill - { - PatternFill = new PatternFill() - { - PatternType = new EnumValue(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.Medium }, - RightBorder = new RightBorder() { Style = BorderStyleValues.Medium }, - TopBorder = new TopBorder() { Style = BorderStyleValues.Medium }, - BottomBorder = new BottomBorder() { Style = BorderStyleValues.Medium }, - DiagonalBorder = new DiagonalBorder() { Style = BorderStyleValues.Medium }, - }); - 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 = 1, - FormatId = 0, - FontId = 0, - BorderId = 1, - FillId = 0, - Alignment = new Alignment() - { - Horizontal = HorizontalAlignmentValues.Left, - Vertical = VerticalAlignmentValues.Center, - WrapText = true - } - }); - cellFormats.Append(new CellFormat - { - NumberFormatId = 2, - FormatId = 0, - FontId = 1, - BorderId = 0, - FillId = 0, - Alignment = new Alignment() - { - Horizontal = HorizontalAlignmentValues.Left, - Vertical = VerticalAlignmentValues.Center, - WrapText = true - } - }); - cellFormats.Append(new CellFormat - { - NumberFormatId = 3, - FormatId = 0, - FontId = 1, - BorderId = 1, - FillId = 0, - Alignment = new Alignment() - { - Horizontal = HorizontalAlignmentValues.Left, - 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().FirstOrDefault(r => r.RowIndex! == rowIndex); - if (row == null) - { - row = new Row() { RowIndex = rowIndex }; - _sheetData.Append(row); - } - var newCell = row.Elements().FirstOrDefault(c => c.CellReference != null && c.CellReference.Value == columnName + rowIndex); - if (newCell == null) - { - Cell? refCell = null; - foreach (Cell cell in row.Elements()) - { - if (cell.CellReference?.Value != null && cell.CellReference.Value.Length == cellReference.Length) + for (var j = 0; j < data[i].Length; ++j) { - if (string.Compare(cell.CellReference.Value, cellReference, true) > 0) + 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.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().First()); + } + spreadsheetDocument.WorkbookPart.Workbook.Save(); + } + + private static void GenerateStyle(WorkbookPart workbookPart) + { + var workbookStylesPart = workbookPart.AddNewPart(); + 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.Minor) + } + }); + + fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font + { + FontSize = new FontSize() { Val = 11 }, + FontName = new FontName() { Val = "Calibri" }, + Bold = new Bold(), + FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 }, + FontScheme = new FontScheme() + { + Val = new EnumValue(FontSchemeValues.Minor) + } + }); + workbookStylesPart.Stylesheet.Append(fonts); + // Default Fill + var fills = new Fills() { Count = 1 }; + fills.Append(new Fill + { + PatternFill = new PatternFill() + { + PatternType = new EnumValue(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.Medium }, + RightBorder = new RightBorder() { Style = BorderStyleValues.Medium }, + TopBorder = new TopBorder() { Style = BorderStyleValues.Medium }, + BottomBorder = new BottomBorder() { Style = BorderStyleValues.Medium }, + DiagonalBorder = new DiagonalBorder() { Style = BorderStyleValues.Medium }, + }); + 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 = 1, + FormatId = 0, + FontId = 0, + BorderId = 1, + FillId = 0, + Alignment = new Alignment() + { + Horizontal = HorizontalAlignmentValues.Left, + Vertical = VerticalAlignmentValues.Center, + WrapText = true + } + }); + cellFormats.Append(new CellFormat + { + NumberFormatId = 2, + FormatId = 0, + FontId = 1, + BorderId = 0, + FillId = 0, + Alignment = new Alignment() + { + Horizontal = HorizontalAlignmentValues.Left, + Vertical = VerticalAlignmentValues.Center, + WrapText = true + } + }); + cellFormats.Append(new CellFormat + { + NumberFormatId = 3, + FormatId = 0, + FontId = 1, + BorderId = 1, + FillId = 0, + Alignment = new Alignment() + { + Horizontal = HorizontalAlignmentValues.Left, + 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().FirstOrDefault(r => r.RowIndex! == rowIndex); + if (row == null) + { + row = new Row() { RowIndex = rowIndex }; + _sheetData.Append(row); + } + var newCell = row.Elements().FirstOrDefault(c => c.CellReference != null && c.CellReference.Value == columnName + rowIndex); + if (newCell == null) + { + Cell? refCell = null; + foreach (Cell cell in row.Elements()) + { + if (cell.CellReference?.Value != null && cell.CellReference.Value.Length == cellReference.Length) { - refCell = cell; - break; + if (string.Compare(cell.CellReference.Value, cellReference, true) > 0) + { + refCell = cell; + break; + } } } + newCell = new Cell() { CellReference = cellReference }; + row.InsertBefore(newCell, refCell); } - newCell = new Cell() { CellReference = cellReference }; - row.InsertBefore(newCell, refCell); + newCell.CellValue = new CellValue(text); + newCell.DataType = CellValues.String; + newCell.StyleIndex = (uint)styleIndex; } - 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) + private static string GetExcelColumnName(int columnNumber) { - modulo = (dividend - 1) % 26; - columnName = Convert.ToChar(65 + modulo).ToString() + - columnName; - dividend = (dividend - modulo) / 26; + 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; } - return columnName; } - -} \ No newline at end of file +} diff --git a/Atelier/Atelier/Reports/TableReport.cs b/Atelier/Atelier/Reports/TableReport.cs index 6c2653c..04a6528 100644 --- a/Atelier/Atelier/Reports/TableReport.cs +++ b/Atelier/Atelier/Reports/TableReport.cs @@ -1,5 +1,6 @@ -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; +using Atelier.Repositories; +using DocumentFormat.OpenXml.Office2010.Excel; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -11,7 +12,7 @@ namespace Atelier.Reports private readonly IOrderRepository _orderRepository; private readonly IModelRepository _modelRepository; private readonly ILogger _logger; - internal static readonly string[] item = ["Клиент", "Дата", "Модель", "Статус", "Новые заказы", "Заказы в работе", "Выполненные заказы"]; + internal static readonly string[] Headers = { "Клиент", "Дата", "Модель", "Статус", "Новые заказы", "Заказы в работе", "Выполненные заказы" }; public TableReport(IOrderRepository orderRepository, IModelRepository modelRepository, ILogger logger) { @@ -20,14 +21,14 @@ namespace Atelier.Reports _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - public bool CreateTable(string filePath, int modelId, DateTime startDate, DateTime endDate) + public bool CreateTable(string filePath, int? modelId = null, DateTime? startDate = null, DateTime? endDate = null, Status? status = null, int? clientId = null) { try { new ExcelBuilder(filePath) .AddHeader("Сводка по заказам", 0, 4) - .AddParagraph("за период", 0) - .AddTable(new[] { 15, 15, 15, 15, 15, 15, 15 }, GetData(modelId, startDate, endDate)) + .AddParagraph($"за период с {startDate:dd.MM.yyyy} по {endDate:dd.MM.yyyy}", 0) + .AddTable(new[] { 15, 15, 15, 15, 15, 15, 15 }, GetData(modelId, startDate, endDate, status, clientId)) .Build(); return true; } @@ -38,15 +39,11 @@ namespace Atelier.Reports } } - private List GetData(int modelId, DateTime startDate, DateTime endDate) + private List GetData(int? modelId, DateTime? startDate, DateTime? endDate, Status? status, int? clientId) { - var orders = _orderRepository - .ReadOrders(modelId, startDate, endDate) - .ToList(); + var orders = _orderRepository.ReadOrders(modelId, startDate, endDate, status, clientId).ToList(); - _logger.LogDebug("Orders: {Orders}", JsonConvert.SerializeObject(orders)); - - var result = new List() { item }; + var result = new List() { Headers }; var newOrdersCount = 0; var inProcessOrdersCount = 0; @@ -54,17 +51,20 @@ namespace Atelier.Reports foreach (var order in orders) { - var model = _modelRepository.ReadModelById(modelId); - var modelName = model?.ModelType.ToString() ?? "Неизвестно"; - var newOrder = order.Status == Status.Waiting ? "1" : "0"; - var inProcessOrder = order.Status == Status.InProcess ? "1" : "0"; - var doneOrder = order.Status == Status.Done ? "1" : "0"; + foreach (var modelOrder in order.ModelOrder) + { + var model = _modelRepository.ReadModelById(modelOrder.ModelId); + var modelName = model?.ModelType.ToString() ?? "Неизвестно"; + var newOrder = order.Status == Status.Waiting ? "1" : "0"; + var inProcessOrder = order.Status == Status.InProcess ? "1" : "0"; + var doneOrder = order.Status == Status.Done ? "1" : "0"; - result.Add(new string[] { order.ClientId.ToString(), order.Date.ToString("yyyy-MM-dd"), modelName, order.Status.ToString(), newOrder, inProcessOrder, doneOrder }); + result.Add(new string[] { order.ClientName, order.Date.ToString("yyyy-MM-dd"), modelName, order.Status.ToString(), newOrder, inProcessOrder, doneOrder }); - if (order.Status == Status.Waiting) newOrdersCount++; - if (order.Status == Status.InProcess) inProcessOrdersCount++; - if (order.Status == Status.Done) doneOrdersCount++; + if (order.Status == Status.Waiting) newOrdersCount++; + if (order.Status == Status.InProcess) inProcessOrdersCount++; + if (order.Status == Status.Done) doneOrdersCount++; + } } result.Add(new[] { "Всего", "", "", "", newOrdersCount.ToString(), inProcessOrdersCount.ToString(), doneOrdersCount.ToString() }); diff --git a/Atelier/Atelier/Repositories/IStorageRepository.cs b/Atelier/Atelier/Repositories/IStorageRepository.cs index c4381bb..d032f75 100644 --- a/Atelier/Atelier/Repositories/IStorageRepository.cs +++ b/Atelier/Atelier/Repositories/IStorageRepository.cs @@ -1,6 +1,6 @@ public interface IStorageRepository { - IEnumerable ReadStorage(int? fabricId = null, double ? StockMetrage = null, double? maxStockMetrage = null); + IEnumerable ReadStorage(int? fabricId = null, double? StockMetrage = null, DateTime? startDate = null, DateTime? endDate = null); void CreateStorage(Storage storage); void DeleteStorage(int id); } diff --git a/Atelier/Atelier/Repositories/Implementations/ModelRepository.cs b/Atelier/Atelier/Repositories/Implementations/ModelRepository.cs index ffb46fe..3993071 100644 --- a/Atelier/Atelier/Repositories/Implementations/ModelRepository.cs +++ b/Atelier/Atelier/Repositories/Implementations/ModelRepository.cs @@ -1,9 +1,12 @@ using Atelier.Repositories; using Dapper; +using DocumentFormat.OpenXml.Drawing.Charts; +using DocumentFormat.OpenXml.Office2010.Excel; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Npgsql; using System.Collections.Generic; +using System.Windows.Forms; internal class ModelRepository : IModelRepository { @@ -160,7 +163,14 @@ internal class ModelRepository : IModelRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = "SELECT * FROM Models"; + var querySelect = @$"SELECT +m.*, +fm.FabricId, +fm.Count, +f.FabricType as FabricName +FROM Models m +INNER JOIN FabricModel fm on fm.ModelId = m.Id +LEFT JOIN Fabrics f ON f.Id = fm.FabricId;"; var models = connection.Query(querySelect).ToList(); foreach (var model in models) diff --git a/Atelier/Atelier/Repositories/Implementations/OrderRepository.cs b/Atelier/Atelier/Repositories/Implementations/OrderRepository.cs index 106517e..f499825 100644 --- a/Atelier/Atelier/Repositories/Implementations/OrderRepository.cs +++ b/Atelier/Atelier/Repositories/Implementations/OrderRepository.cs @@ -3,15 +3,16 @@ using Dapper; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Npgsql; -using Serilog.Core; - +using System.Text; +using System.Collections.Generic; +using System.Linq; internal class OrderRepository : IOrderRepository { private readonly IConnectionString _connectionString; private readonly ILogger _logger; - public OrderRepository(IConnectionString connectionString, - ILogger logger) + + public OrderRepository(IConnectionString connectionString, ILogger logger) { _connectionString = connectionString; _logger = logger; @@ -20,23 +21,20 @@ internal class OrderRepository : IOrderRepository public void CreateOrder(Order order) { _logger.LogInformation("Добавление объекта"); - _logger.LogDebug("Объект: {json}", - JsonConvert.SerializeObject(order)); + _logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(order)); try { - using var connection = new - NpgsqlConnection(_connectionString.ConnectionString); + using var connection = new NpgsqlConnection(_connectionString.ConnectionString); connection.Open(); using var transaction = connection.BeginTransaction(); var queryInsert = @" INSERT INTO Orders (Date, Status, ClientId) VALUES (@Date, @Status, @ClientId); SELECT MAX(Id) FROM Orders"; - var orderId = - connection.QueryFirst(queryInsert, order, transaction); + var orderId = connection.QueryFirst(queryInsert, order, transaction); var querySubInsert = @" INSERT INTO ModelOrder (OrderId, ModelId, Count) -VALUES (@OrderId,@ModelId, @Count)"; +VALUES (@OrderId, @ModelId, @Count)"; foreach (var elem in order.ModelOrder) { connection.Execute(querySubInsert, new @@ -53,19 +51,18 @@ VALUES (@OrderId,@ModelId, @Count)"; _logger.LogError(ex, "Ошибка при добавлении объекта"); throw; } - } + public void DeleteOrder(int id) { _logger.LogInformation("Удаление объекта"); _logger.LogDebug("Объект: {id}", id); try { - using var connection = new - NpgsqlConnection(_connectionString.ConnectionString); + using var connection = new NpgsqlConnection(_connectionString.ConnectionString); var queryDelete = @" DELETE FROM Orders -WHERE Id=@id"; +WHERE Id = @id"; connection.Execute(queryDelete, new { id }); } catch (Exception ex) @@ -73,70 +70,106 @@ WHERE Id=@id"; _logger.LogError(ex, "Ошибка при удалении объекта"); throw; } - } + 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() + { + return _builder.Length == 0 ? string.Empty : $"WHERE {_builder}"; + } + } public IEnumerable ReadOrders(int? modelId = null, DateTime? startDate = null, DateTime? endDate = null, Status? status = null, int? clientId = null) { _logger.LogInformation("Получение всех объектов"); try { - using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = @" - SELECT o.Id, o.Date, o.Status, o.ClientId, m.ModelId, m.Count, m.OrderId - FROM Orders o - LEFT JOIN ModelOrder m ON o.Id = m.OrderId"; - - var parameters = new DynamicParameters(); - if (modelId.HasValue) - { - querySelect += " WHERE m.ModelId = @ModelId"; - parameters.Add("@ModelId", modelId.Value); - } + var builder = new QueryBuilder(); if (startDate.HasValue) { - querySelect += " AND o.Date >= @StartDate"; - parameters.Add("@StartDate", startDate.Value); + builder.AddCondition("o.Date >= @startDate"); } if (endDate.HasValue) { - querySelect += " AND o.Date <= @EndDate"; - parameters.Add("@EndDate", endDate.Value); + builder.AddCondition("o.Date <= @endDate"); + } + if (modelId.HasValue) + { + builder.AddCondition("mo.ModelId = @modelId"); } if (status.HasValue) { - querySelect += " AND o.Status = @Status"; - parameters.Add("@Status", status.Value); + builder.AddCondition("o.Status = @status"); } if (clientId.HasValue) { - querySelect += " AND o.ClientId = @ClientId"; - parameters.Add("@ClientId", clientId.Value); + builder.AddCondition("o.ClientId = @clientId"); } + using var connection = new NpgsqlConnection(_connectionString.ConnectionString); + var querySelect = @$" +SELECT +o.*, +CONCAT(c.LastName, ' ', c.FirstName) as ClientName, +mo.ModelId, +mo.Count, +m.ModelType as ModelName +FROM Orders o +LEFT JOIN Clients c on c.Id = o.ClientId +INNER JOIN ModelOrder mo on mo.OrderId = o.Id +LEFT JOIN Models m ON m.Id = mo.ModelId +{builder.Build()}"; + + var orderDict = new Dictionary>(); var orders = connection.Query( querySelect, (order, modelOrder) => { - var newOrder = Order.CreateOperation(order.Id, order.Date, order.Status, order.ClientId, new List()); - if (modelOrder != null) + if (!orderDict.TryGetValue(order.Id, out var modelOrders)) { - var modelOrders = new List(newOrder.ModelOrder); - modelOrders.Add(modelOrder); - newOrder = Order.CreateOperation(order.Id, order.Date, order.Status, order.ClientId, modelOrders); + modelOrders = new List(); + orderDict.Add(order.Id, modelOrders); } - return newOrder; + modelOrders.Add(modelOrder); + return order; }, - param: parameters, - splitOn: "OrderId").ToList(); + splitOn: "ModelId", + param: new + { + startDate, + endDate, + modelId, + status, + clientId + }); _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(orders)); - return orders; + + return orderDict.Select(x => + { + var o = orders.First(y => y.Id == x.Key); + o.SetModelOrder(x.Value); + return o; + }).ToArray(); } catch (Exception ex) { - _logger.LogError(ex, "Ошибка при чтении данных о заказах"); + _logger.LogError(ex, "Ошибка при чтении объектов"); throw; } } diff --git a/Atelier/Atelier/Repositories/Implementations/StorageRepository.cs b/Atelier/Atelier/Repositories/Implementations/StorageRepository.cs index 88a8ee3..46dfd06 100644 --- a/Atelier/Atelier/Repositories/Implementations/StorageRepository.cs +++ b/Atelier/Atelier/Repositories/Implementations/StorageRepository.cs @@ -3,6 +3,8 @@ using Dapper; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Npgsql; +using System.Text; +using static System.Runtime.InteropServices.JavaScript.JSType; internal class StorageRepository : IStorageRepository { @@ -52,22 +54,81 @@ WHERE Id=@id"; throw; } } - public IEnumerable ReadStorage(int? fabricId = null, double? minStockMetrage = null, double? StockMetrage = null) + 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}"; + } + } + + public IEnumerable ReadStorage(int? fabricId = null, double? stockMetrage = null, DateTime? startDate = null, DateTime? endDate = null) { _logger.LogInformation("Получение всех данных о складе"); try { - using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = "SELECT * FROM Storages"; - var storages = connection.Query(querySelect).ToList(); + var builder = new QueryBuilder(); + if (startDate.HasValue) + { + builder.AddCondition("s.DateStorage >= @startDate"); + } + if (endDate.HasValue) + { + builder.AddCondition("s.DateStorage <= @endDate"); + } + if (fabricId.HasValue) + { + builder.AddCondition("s.FabricId = @fabricId"); + } + if (stockMetrage.HasValue) + { + builder.AddCondition("s.StockMetrage = @stockMetrage"); + } - _logger.LogDebug("Полученные данные о складе: {json}", JsonConvert.SerializeObject(storages)); - return storages; + + using var connection = new NpgsqlConnection(_connectionString.ConnectionString); + var querySelect = @$" +SELECT +s.*, +f.FabricType as FabricName +FROM Storages s +LEFT JOIN Fabrics f on f.Id = s.FabricId +{builder.Build()}"; + + var storage = connection.Query(querySelect, new + { + startDate, + endDate, + fabricId, + stockMetrage + }); + _logger.LogDebug("Полученные объекты: {json}", + JsonConvert.SerializeObject(storage)); + return storage; } catch (Exception ex) { - _logger.LogError(ex, "Ошибка при чтении данных о складе"); + _logger.LogError(ex, "Ошибка при чтении объектов"); throw; } } } +