From 8dceb4b4e0c293b16dec12308883ae4ce0a6930c Mon Sep 17 00:00:00 2001 From: "DozorovaA.A" Date: Sat, 20 May 2023 02:44:53 +0400 Subject: [PATCH] generate files --- .../BusinessLogics/ReportStorekeeperLogic.cs | 72 +++- .../MailWorker/MailWorker.cs | 4 +- .../StoreKeeper/SaveStoreKeeperToExcel.cs | 321 ++++++++++++++++++ .../StoreKeeper/SaveStoreKeeperToPdf.cs | 109 ++++++ .../StoreKeeper/SaveStoreKeeperToWord.cs | 125 +++++++ .../BindingModels/ReportBindingModel.cs | 4 +- .../IReportStorekeeperLogic.cs | 2 +- .../SearchModels/FurnitureSearchModel.cs | 3 + .../ViewModels/ReportMaterialsViewModel.cs | 1 - .../Implements/FurnitureStorage.cs | 19 ++ .../ReportStorekeeperController.cs | 75 ++++ .../FurnitureAssemblyRestApi/DocFile | Bin 0 -> 1315 bytes .../FurnitureAssemblyRestApi/Program.cs | 7 + .../pdf_storekeeper.pdf | Bin 0 -> 26141 bytes .../APIClient.cs | 20 +- .../Controllers/HomeController.cs | 161 ++++++++- .../ExelFile | Bin 0 -> 2958 bytes ...rnitureAssemblyStoreKeeperClientApp.csproj | 1 + .../Program.cs | 8 + .../Views/Home/CreateListMaterials.cshtml | 60 ++++ .../Views/Home/CreateReport.cshtml | 77 +++++ .../Views/Shared/_Layout.cshtml | 5 +- 22 files changed, 1046 insertions(+), 28 deletions(-) create mode 100644 FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToExcel.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToPdf.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToWord.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyRestApi/Controllers/ReportStorekeeperController.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyRestApi/DocFile create mode 100644 FurnitureAssembly/FurnitureAssemblyRestApi/pdf_storekeeper.pdf create mode 100644 FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/ExelFile create mode 100644 FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateListMaterials.cshtml create mode 100644 FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateReport.cshtml diff --git a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/ReportStorekeeperLogic.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/ReportStorekeeperLogic.cs index be496b8..812c9ed 100644 --- a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/ReportStorekeeperLogic.cs +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/ReportStorekeeperLogic.cs @@ -1,4 +1,7 @@ -using FurnitureAssemblyContracts.BindingModels; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels; +using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile; +using FurnitureAssemblyContracts.BindingModels; +using FurnitureAssemblyContracts.SearchModels; using FurnitureAssemblyContracts.StorageContracts; using FurnitureAssemblyContracts.ViewModels; using System; @@ -16,31 +19,34 @@ namespace FurnitureAssemblyBusinessLogic.BusinessLogics private readonly AbstractSaveToWord _saveToWord; private readonly AbstractSaveToPdf _saveToPdf; - public ReportLogic(IFurnitureStorage furnitureStorage, IOrderStorage orderStorage, + public ReportStorekeeperLogic(IFurnitureStorage furnitureStorage, AbstractSaveToExcel saveToExcel, AbstractSaveToWord saveToWord, AbstractSaveToPdf saveToPdf) { _furnitureStorage = furnitureStorage; - _orderStorage = orderStorage; _saveToExcel = saveToExcel; _saveToWord = saveToWord; _saveToPdf = saveToPdf; } - public List GetFurnitureComponent() + public List GetFurnitureComponent(int[]? ids) { - var furnitures = _furnitureStorage.GetFullList(); + var furnitures = _furnitureStorage.GetFullList().Where(x => ids.Contains(x.Id)); + if(ids == null) + { + furnitures = _furnitureStorage.GetFullList(); + } var list = new List(); foreach (var furniture in furnitures) { - var record = new ReportFurnitureComponentViewModel + var record = new ReportFurnitureMaterialViewModel { - FurnitureName = furniture.FurnitureName, - Components = new List>(), + FurnitureName = furniture.Name, + Materials = new List>(), TotalCount = 0 }; - foreach (var componentCount in furniture.FurnitureComponents.Values) + foreach (var materials in furniture.FurnitureMaterials.Values) { - record.Components.Add(new Tuple(componentCount.Item1.ComponentName, componentCount.Item2)); - record.TotalCount += componentCount.Item2; + record.Materials.Add(new Tuple(materials.Item1.Name, materials.Item2)); + record.TotalCount += materials.Item2; } list.Add(record); } @@ -49,22 +55,58 @@ namespace FurnitureAssemblyBusinessLogic.BusinessLogics public List GetOrders(ReportBindingModel model) { - throw new NotImplementedException(); + var furnitures = _furnitureStorage.GetFilteredList(new FurnitureSearchModel + { + DateFrom = model.DateFrom, + DateTo = model.DateTo + }) + .Select(x => new MaterialViewModel + { + Name = x.Name, + Cost = x.Cost, + }) + .ToList(); + + var materialsList = new List(); + + materialsList = furnitures.GroupBy(x => x.Name).Select(x => new ReportMaterialsViewModel + { + MaterialName = x.Key, + Sum = x.Sum(x => x.Cost) + }).ToList(); + return materialsList; } public void SaveFurnituresToExelFile(ReportBindingModel model) { - throw new NotImplementedException(); + _saveToExcel.CreateReport(new ExcelStoreKeeperInfo + { + FileName = model.FileName, + Title = "Список мебели", + FurnitureMaterials = GetFurnitureComponent(model.Ids) + }); } public void SaveFurnituresToWordFile(ReportBindingModel model) { - throw new NotImplementedException(); + _saveToWord.CreateDoc(new WordStoreKeeperInfo + { + FileName = model.FileName, + Title = "Список мебели", + FurnitureMaterialsList = GetFurnitureComponent(model.Ids) + }); } public void SaveMaterialsToPdfFile(ReportBindingModel model) { - throw new NotImplementedException(); + _saveToPdf.CreateDoc(new PdfStoreKeeperInfo + { + FileName = model.FileName, + Title = "Список заказов", + DateFrom = model.DateFrom!.Value, + DateTo = model.DateTo!.Value, + Materials = GetOrders(model) + }); } } } diff --git a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/MailWorker.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/MailWorker.cs index 20a1331..2575194 100644 --- a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/MailWorker.cs +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/MailWorker.cs @@ -51,7 +51,9 @@ namespace FurnitureAssemblyBusinessLogic.MailWorker objMailMessage.Body = info.Text; objMailMessage.SubjectEncoding = Encoding.UTF8; objMailMessage.BodyEncoding = Encoding.UTF8; - Attachment attachment = new Attachment("C:\\temp\\pdf_worker.pdf", new ContentType(MediaTypeNames.Application.Pdf)); + var path = File.Exists("C:\\temp\\pdf_worker.pdf") ? "C:\\temp\\pdf_worker.pdf" : "C:\\temp\\pdf_storekeeper.pdf"; + + Attachment attachment = new Attachment(path, new ContentType(MediaTypeNames.Application.Pdf)); objMailMessage.Attachments.Add(attachment); objSmtpClient.UseDefaultCredentials = false; diff --git a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToExcel.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToExcel.cs new file mode 100644 index 0000000..b85f710 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToExcel.cs @@ -0,0 +1,321 @@ +using DocumentFormat.OpenXml.Office2010.Excel; +using DocumentFormat.OpenXml.Office2013.Excel; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; +using DocumentFormat.OpenXml; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperEnums; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels; + +namespace FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper +{ + public class SaveStoreKeeperToExcel : AbstractSaveToExcel + { + private SpreadsheetDocument? _spreadsheetDocument; + private SharedStringTablePart? _shareStringPart; + private Worksheet? _worksheet; + /// + /// Настройка стилей для файла + /// + /// + private static void CreateStyles(WorkbookPart workbookpart) + { + var sp = workbookpart.AddNewPart(); + sp.Stylesheet = new Stylesheet(); + var fonts = new Fonts() { Count = 2U, KnownFonts = true }; + var fontUsual = new Font(); + fontUsual.Append(new FontSize() { Val = 12D }); + fontUsual.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Theme = 1U }); + fontUsual.Append(new FontName() { Val = "Times New Roman" }); + fontUsual.Append(new FontFamilyNumbering() { Val = 2 }); + fontUsual.Append(new FontScheme() { Val = FontSchemeValues.Minor }); + var fontTitle = new Font(); + fontTitle.Append(new Bold()); + fontTitle.Append(new FontSize() { Val = 14D }); + fontTitle.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Theme = 1U }); + fontTitle.Append(new FontName() { Val = "Times New Roman" }); + fontTitle.Append(new FontFamilyNumbering() { Val = 2 }); + fontTitle.Append(new FontScheme() { Val = FontSchemeValues.Minor }); + fonts.Append(fontUsual); + fonts.Append(fontTitle); + var fills = new Fills() { Count = 2U }; + var fill1 = new Fill(); + fill1.Append(new PatternFill() { PatternType = PatternValues.None }); + var fill2 = new Fill(); + fill2.Append(new PatternFill() + { + PatternType = PatternValues.Gray125 + }); + fills.Append(fill1); + fills.Append(fill2); + var borders = new Borders() { Count = 2U }; + var borderNoBorder = new Border(); + borderNoBorder.Append(new LeftBorder()); + borderNoBorder.Append(new RightBorder()); + borderNoBorder.Append(new TopBorder()); + borderNoBorder.Append(new BottomBorder()); + borderNoBorder.Append(new DiagonalBorder()); + var borderThin = new Border(); + var leftBorder = new LeftBorder() { Style = BorderStyleValues.Thin }; + leftBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + var rightBorder = new RightBorder() + { + Style = BorderStyleValues.Thin + }; + rightBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + var topBorder = new TopBorder() { Style = BorderStyleValues.Thin }; + topBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + var bottomBorder = new BottomBorder() + { + Style = BorderStyleValues.Thin + }; + bottomBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + borderThin.Append(leftBorder); + borderThin.Append(rightBorder); + borderThin.Append(topBorder); + borderThin.Append(bottomBorder); + borderThin.Append(new DiagonalBorder()); + borders.Append(borderNoBorder); + borders.Append(borderThin); + var cellStyleFormats = new CellStyleFormats() { Count = 1U }; + var cellFormatStyle = new CellFormat() + { + NumberFormatId = 0U, + FontId = 0U, + FillId = 0U, + BorderId = 0U + }; + cellStyleFormats.Append(cellFormatStyle); + var cellFormats = new CellFormats() { Count = 3U }; + var cellFormatFont = new CellFormat() + { + NumberFormatId = 0U, + FontId = 0U, + FillId = 0U, + BorderId = 0U, + FormatId = 0U, + ApplyFont = true + }; + var cellFormatFontAndBorder = new CellFormat() + { + NumberFormatId = 0U, + FontId = 0U, + FillId = 0U, + BorderId = 1U, + FormatId = 0U, + ApplyFont = true, + ApplyBorder = true + }; + var cellFormatTitle = new CellFormat() + { + NumberFormatId = 0U, + FontId = 1U, + FillId = 0U, + BorderId = 0U, + FormatId = 0U, + Alignment = new Alignment() + { + Vertical = VerticalAlignmentValues.Center, + WrapText = true, + Horizontal = HorizontalAlignmentValues.Center + }, + ApplyFont = true + }; + cellFormats.Append(cellFormatFont); + cellFormats.Append(cellFormatFontAndBorder); + cellFormats.Append(cellFormatTitle); + var cellStyles = new CellStyles() { Count = 1U }; + cellStyles.Append(new CellStyle() + { + Name = "Normal", + FormatId = 0U, + BuiltinId = 0U + }); + var differentialFormats = new DocumentFormat.OpenXml.Office2013.Excel.DifferentialFormats() { Count = 0U }; + var tableStyles = new TableStyles() + { + Count = 0U, + DefaultTableStyle = "TableStyleMedium2", + DefaultPivotStyle = "PivotStyleLight16" + }; + var stylesheetExtensionList = new StylesheetExtensionList(); + var stylesheetExtension1 = new StylesheetExtension() + { + Uri = "{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" + }; + stylesheetExtension1.AddNamespaceDeclaration("x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"); + stylesheetExtension1.Append(new SlicerStyles() + { + DefaultSlicerStyle = "SlicerStyleLight1" + }); + var stylesheetExtension2 = new StylesheetExtension() + { + Uri = "{9260A510-F301-46a8-8635-F512D64BE5F5}" + }; + stylesheetExtension2.AddNamespaceDeclaration("x15", "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"); + stylesheetExtension2.Append(new TimelineStyles() + { + DefaultTimelineStyle = "TimeSlicerStyleLight1" + }); + stylesheetExtensionList.Append(stylesheetExtension1); + stylesheetExtensionList.Append(stylesheetExtension2); + sp.Stylesheet.Append(fonts); + sp.Stylesheet.Append(fills); + sp.Stylesheet.Append(borders); + sp.Stylesheet.Append(cellStyleFormats); + sp.Stylesheet.Append(cellFormats); + sp.Stylesheet.Append(cellStyles); + sp.Stylesheet.Append(differentialFormats); + sp.Stylesheet.Append(tableStyles); + sp.Stylesheet.Append(stylesheetExtensionList); + } + /// + /// Получение номера стиля из типа + /// + /// + /// + private static uint GetStyleValue(ExcelStyleInfoType styleInfo) + { + return styleInfo switch + { + ExcelStyleInfoType.Title => 2U, + ExcelStyleInfoType.TextWithBroder => 1U, + ExcelStyleInfoType.Text => 0U, + _ => 0U, + }; + } + protected override void CreateExcel(ExcelStoreKeeperInfo info) + { + _spreadsheetDocument = SpreadsheetDocument.Create(info.FileName, SpreadsheetDocumentType.Workbook); + // Создаем книгу (в ней хранятся листы) + var workbookpart = _spreadsheetDocument.AddWorkbookPart(); + workbookpart.Workbook = new Workbook(); + CreateStyles(workbookpart); + // Получаем/создаем хранилище текстов для книги + _shareStringPart = _spreadsheetDocument.WorkbookPart!.GetPartsOfType().Any() + ? _spreadsheetDocument.WorkbookPart.GetPartsOfType().First() + : _spreadsheetDocument.WorkbookPart.AddNewPart(); + // Создаем SharedStringTable, если его нет + if (_shareStringPart.SharedStringTable == null) + { + _shareStringPart.SharedStringTable = new SharedStringTable(); + } + // Создаем лист в книгу + var worksheetPart = workbookpart.AddNewPart(); + worksheetPart.Worksheet = new Worksheet(new SheetData()); + // Добавляем лист в книгу + var sheets = _spreadsheetDocument.WorkbookPart.Workbook.AppendChild(new Sheets()); + var sheet = new Sheet() + { + Id = _spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), + SheetId = 1, + Name = "Лист" + }; + sheets.Append(sheet); + _worksheet = worksheetPart.Worksheet; + } + protected override void InsertCellInWorksheet(ExcelCellParameters excelParams) + { + if (_worksheet == null || _shareStringPart == null) + { + return; + } + var sheetData = _worksheet.GetFirstChild(); + if (sheetData == null) + { + return; + } + // Ищем строку, либо добавляем ее + Row row; + if (sheetData.Elements().Where(r => r.RowIndex! == excelParams.RowIndex).Any()) + { + row = sheetData.Elements().Where(r => r.RowIndex! == excelParams.RowIndex).First(); + } + else + { + row = new Row() { RowIndex = excelParams.RowIndex }; + sheetData.Append(row); + } + // Ищем нужную ячейку + Cell cell; + if (row.Elements().Where(c => c.CellReference!.Value == excelParams.CellReference).Any()) + { + cell = row.Elements().Where(c => c.CellReference!.Value == excelParams.CellReference).First(); + } + else + { + // Все ячейки должны быть последовательно друг за другом расположены + // нужно определить, после какой вставлять + Cell? refCell = null; + foreach (Cell rowCell in row.Elements()) + { + if (string.Compare(rowCell.CellReference!.Value, + excelParams.CellReference, true) > 0) + { + refCell = rowCell; + break; + } + } + var newCell = new Cell() + { + CellReference = excelParams.CellReference + }; + row.InsertBefore(newCell, refCell); + cell = newCell; + } + // вставляем новый текст + _shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new Text(excelParams.Text))); + _shareStringPart.SharedStringTable.Save(); + cell.CellValue = new + CellValue((_shareStringPart.SharedStringTable.Elements().Count() - 1).ToString()); + cell.DataType = new EnumValue(CellValues.SharedString); + cell.StyleIndex = GetStyleValue(excelParams.StyleInfo); + } + protected override void MergeCells(ExcelMergeParameters excelParams) + { + if (_worksheet == null) + { + return; + } + MergeCells mergeCells; + if (_worksheet.Elements().Any()) + { + mergeCells = _worksheet.Elements().First(); + } + else + { + mergeCells = new MergeCells(); + if (_worksheet.Elements().Any()) + { + _worksheet.InsertAfter(mergeCells, + _worksheet.Elements().First()); + } + else + { + _worksheet.InsertAfter(mergeCells, + _worksheet.Elements().First()); + } + } + var mergeCell = new MergeCell() + { + Reference = new StringValue(excelParams.Merge) + }; + mergeCells.Append(mergeCell); + } + protected override void SaveExcel(ExcelStoreKeeperInfo info) + { + if (_spreadsheetDocument == null) + { + return; + } + _spreadsheetDocument.WorkbookPart!.Workbook.Save(); + _spreadsheetDocument.Close(); + } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToPdf.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToPdf.cs new file mode 100644 index 0000000..20fa1bc --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToPdf.cs @@ -0,0 +1,109 @@ +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperEnums; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels; +using MigraDoc.DocumentObjectModel; +using MigraDoc.Rendering; +using MigraDoc.DocumentObjectModel.Tables; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels; + +namespace FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper +{ + public class SaveStoreKeeperToPdf : AbstractSaveToPdf + { + private Document? _document; + private Section? _section; + private Table? _table; + private static ParagraphAlignment + GetParagraphAlignment(PdfParagraphAlignmentType type) + { + return type switch + { + PdfParagraphAlignmentType.Center => ParagraphAlignment.Center, + PdfParagraphAlignmentType.Left => ParagraphAlignment.Left, + PdfParagraphAlignmentType.Rigth => ParagraphAlignment.Right, + _ => ParagraphAlignment.Justify, + }; + } + /// + /// Создание стилей для документа + /// + /// + private static void DefineStyles(Document document) + { + var style = document.Styles["Normal"]; + style.Font.Name = "Times New Roman"; + style.Font.Size = 14; + style = document.Styles.AddStyle("NormalTitle", "Normal"); + style.Font.Bold = true; + } + protected override void CreatePdf(PdfStoreKeeperInfo info) + { + _document = new Document(); + DefineStyles(_document); + _section = _document.AddSection(); + } + protected override void CreateParagraph(PdfParagraph pdfParagraph) + { + if (_section == null) + { + return; + } + var paragraph = _section.AddParagraph(pdfParagraph.Text); + paragraph.Format.SpaceAfter = "1cm"; + paragraph.Format.Alignment = + GetParagraphAlignment(pdfParagraph.ParagraphAlignment); + paragraph.Style = pdfParagraph.Style; + } + protected override void CreateTable(List columns) + { + if (_document == null) + { + return; + } + _table = _document.LastSection.AddTable(); + foreach (var elem in columns) + { + _table.AddColumn(elem); + } + } + protected override void CreateRow(PdfRowParameters rowParameters) + { + if (_table == null) + { + return; + } + var row = _table.AddRow(); + for (int i = 0; i < rowParameters.Texts.Count; ++i) + { + row.Cells[i].AddParagraph(rowParameters.Texts[i]); + if (!string.IsNullOrEmpty(rowParameters.Style)) + { + row.Cells[i].Style = rowParameters.Style; + } + Unit borderWidth = 0.5; + row.Cells[i].Borders.Left.Width = borderWidth; + row.Cells[i].Borders.Right.Width = borderWidth; + row.Cells[i].Borders.Top.Width = borderWidth; + row.Cells[i].Borders.Bottom.Width = borderWidth; + row.Cells[i].Format.Alignment = + GetParagraphAlignment(rowParameters.ParagraphAlignment); + row.Cells[i].VerticalAlignment = VerticalAlignment.Center; + } + } + protected override void SavePdf(PdfStoreKeeperInfo info) + { + var renderer = new PdfDocumentRenderer(true) + { + Document = _document + }; + System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); + renderer.RenderDocument(); + renderer.PdfDocument.Save(info.FileName); + } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToWord.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToWord.cs new file mode 100644 index 0000000..34f345d --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/OfficePackage/Implements/StoreKeeper/SaveStoreKeeperToWord.cs @@ -0,0 +1,125 @@ +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Wordprocessing; +using DocumentFormat.OpenXml; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperEnums; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile; +using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels; + +namespace FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper +{ + public class SaveStoreKeeperToWord : AbstractSaveToWord + { + private WordprocessingDocument? _wordDocument; + private Body? _docBody; + /// + /// Получение типа выравнивания + /// + /// + /// + private static JustificationValues GetJustificationValues(WordJustificationType type) + { + return type switch + { + WordJustificationType.Both => JustificationValues.Both, + WordJustificationType.Center => JustificationValues.Center, + _ => JustificationValues.Left, + }; + } + /// + /// Настройки страницы + /// + /// + private static SectionProperties CreateSectionProperties() + { + var properties = new SectionProperties(); + var pageSize = new PageSize + { + Orient = PageOrientationValues.Portrait + }; + properties.AppendChild(pageSize); + return properties; + } + /// + /// Задание форматирования для абзаца + /// + /// + /// + private static ParagraphProperties? CreateParagraphProperties(WordTextProperties? paragraphProperties) + { + if (paragraphProperties == null) + { + return null; + } + var properties = new ParagraphProperties(); + properties.AppendChild(new Justification() + { + Val = GetJustificationValues(paragraphProperties.JustificationType) + }); + properties.AppendChild(new SpacingBetweenLines + { + LineRule = LineSpacingRuleValues.Auto + }); + properties.AppendChild(new Indentation()); + var paragraphMarkRunProperties = new ParagraphMarkRunProperties(); + if (!string.IsNullOrEmpty(paragraphProperties.Size)) + { + paragraphMarkRunProperties.AppendChild(new FontSize + { + Val = paragraphProperties.Size + }); + } + properties.AppendChild(paragraphMarkRunProperties); + return properties; + } + protected override void CreateWord(WordStoreKeeperInfo info) + { + _wordDocument = WordprocessingDocument.Create(info.FileName, WordprocessingDocumentType.Document); + MainDocumentPart mainPart = _wordDocument.AddMainDocumentPart(); + mainPart.Document = new Document(); + _docBody = mainPart.Document.AppendChild(new Body()); + } + protected override void CreateParagraph(WordParagraph paragraph) + { + if (_docBody == null || paragraph == null) + { + return; + } + var docParagraph = new Paragraph(); + docParagraph.AppendChild(CreateParagraphProperties(paragraph.TextProperties)); + foreach (var run in paragraph.Texts) + { + var docRun = new Run(); + var properties = new RunProperties(); + properties.AppendChild(new FontSize { Val = run.Item2.Size }); + if (run.Item2.Bold) + { + properties.AppendChild(new Bold()); + } + docRun.AppendChild(properties); + docRun.AppendChild(new Text + { + Text = run.Item1, + Space = SpaceProcessingModeValues.Preserve + }); + docParagraph.AppendChild(docRun); + } + _docBody.AppendChild(docParagraph); + } + protected override void SaveWord(WordStoreKeeperInfo info) + { + if (_docBody == null || _wordDocument == null) + { + return; + } + _docBody.AppendChild(CreateSectionProperties()); + _wordDocument.MainDocumentPart!.Document.Save(); + _wordDocument.Close(); + } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/ReportBindingModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/ReportBindingModel.cs index 629e40e..5e047db 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/ReportBindingModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/ReportBindingModel.cs @@ -1,4 +1,5 @@ -using System; +using FurnitureAssemblyContracts.ViewModels; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,5 +12,6 @@ namespace FurnitureAssemblyContracts.BindingModels public string FileName { get; set; } = string.Empty; public DateTime? DateFrom { get; set; } public DateTime? DateTo { get; set; } + public int[]? Ids{ get; set; } } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicContracts/IReportStorekeeperLogic.cs b/FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicContracts/IReportStorekeeperLogic.cs index e7b31d4..f172a23 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicContracts/IReportStorekeeperLogic.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicContracts/IReportStorekeeperLogic.cs @@ -14,7 +14,7 @@ namespace FurnitureAssemblyBusinessLogic.BusinessLogics /// Получение списка мебели с разбиением по материалам /// /// - List GetFurnitureComponent(); + List GetFurnitureComponent(int[]? ids); /// /// Получение отчета по движению материалов за период времени diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/SearchModels/FurnitureSearchModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/SearchModels/FurnitureSearchModel.cs index fb78e54..310a7ab 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/SearchModels/FurnitureSearchModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/SearchModels/FurnitureSearchModel.cs @@ -11,5 +11,8 @@ namespace FurnitureAssemblyContracts.SearchModels public int? Id { get; set; } public string? Name { get; set; } public int? UserId { get; set; } + + public DateTime? DateFrom { get; set; } + public DateTime? DateTo { get; set; } } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ReportMaterialsViewModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ReportMaterialsViewModel.cs index 27363e7..b43461c 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ReportMaterialsViewModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ReportMaterialsViewModel.cs @@ -9,7 +9,6 @@ namespace FurnitureAssemblyContracts.ViewModels public class ReportMaterialsViewModel { public int Id { get; set; } - public DateTime DateCreate { get; set; } public string MaterialName { get; set; } = string.Empty; public double Sum { get; set; } } diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/FurnitureStorage.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/FurnitureStorage.cs index 739942d..c6dc9c0 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/FurnitureStorage.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/FurnitureStorage.cs @@ -44,6 +44,25 @@ namespace FurnitureAssemblyDatabaseImplement.Implements .Where(x => x.UserId == model.UserId) .Select(x => x.GetViewModel).ToList(); } + else if(model.DateFrom != null || model.DateTo != null) + { + var dateTo = model.DateTo == null ? DateTime.Now : model.DateTo; + if(model.DateFrom == null) + { + return context.Furnitures + .Include(x => x.User) + .Include(x => x.Materials) + .ThenInclude(x => x.Material) + .Where(x => x.DateCreate < dateTo) + .Select(x => x.GetViewModel).ToList(); + } + else return context.Furnitures + .Include(x => x.User) + .Include(x => x.Materials) + .ThenInclude(x => x.Material) + .Where(x => x.DateCreate < dateTo && x.DateCreate > model.DateFrom) + .Select(x => x.GetViewModel).ToList(); + } else { return new(); diff --git a/FurnitureAssembly/FurnitureAssemblyRestApi/Controllers/ReportStorekeeperController.cs b/FurnitureAssembly/FurnitureAssemblyRestApi/Controllers/ReportStorekeeperController.cs new file mode 100644 index 0000000..7f3298e --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyRestApi/Controllers/ReportStorekeeperController.cs @@ -0,0 +1,75 @@ +using FurnitureAssemblyBusinessLogic.BusinessLogics; +using FurnitureAssemblyBusinessLogic.MailWorker; +using FurnitureAssemblyContracts.BindingModels; +using Microsoft.AspNetCore.Mvc; + +namespace FurnitureAssemblyRestApi.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class ReportStorekeeperController : Controller + { + private readonly ILogger _logger; + private readonly IReportStorekeeperLogic _reportLogic; + private readonly MailWorker _mail; + public ReportStorekeeperController(ILogger logger, IReportStorekeeperLogic reportLogic, MailWorker mailWorker) + { + _logger = logger; + _reportLogic = reportLogic; + _mail = mailWorker; + } + + [HttpPost] + public void CreateReportToDocx(ReportBindingModel model) + { + try + { + _reportLogic.SaveFurnituresToWordFile(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка создания отчета"); + throw; + } + } + [HttpPost] + public void CreateReportToXlsx(ReportBindingModel model) + { + try + { + _reportLogic.SaveFurnituresToExelFile(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка создания отчета"); + throw; + } + } + [HttpPost] + public void CreateReportOrdersToPdf(ReportBindingModel model) + { + try + { + _reportLogic.SaveMaterialsToPdfFile(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка создания отчета"); + throw; + } + } + [HttpPost] + public void SendPdfToMail(MailSendInfoBindingModel model) + { + try + { + _mail.MailSendAsync(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка отправки письма"); + throw; + } + } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyRestApi/DocFile b/FurnitureAssembly/FurnitureAssemblyRestApi/DocFile new file mode 100644 index 0000000000000000000000000000000000000000..44e384004a6d970a99d8dd2a704a99f3c9b331ef GIT binary patch literal 1315 zcmWIWW@Zs#VBp|j_$#s{%yPlz>F$gS4B9LV41x>{4CVPnDf%h-$)&lec_n%kxj9!S zJNg|q5O7_eROv6P<)D#uOIyLB@%4_ifl1NH%Nfh2cyCBN$m_rnvXx`qgF79bmlPsI zj<6k6`l#~x@4o$OBzw+%>N%roky_$ZUM;8^#64Nd);Hs!x^;VriOiJ3ESHJiZ#iFW z?LOUdZqIhZWWO^h=VH%CtlVgBIH9Nt zZ>yAb+&hOW=veVQ)sO`ux!f6=?-nio@?DDa z_LdvF1#47~Z?3%)dd&CDGm(rOM=Q=^&-RCAd)iV)?9N)_U3=_>qqwamc;5BTz0OwIq8Jw z!|0~D^R84db1mnVWV0!FYCYetBh`9NL`k!K4RZiA)EO9~-^jqgOdn_?!VD!;GZjKA3sQ+OF+VLWGda}-nrN^XtdFWfNg*V$C_S~rR!JWt zxhW}lrr0V4nHd>dSQr{wni?8dnj~8!DJkgN+32JA*bX&F?@KdP#)P0aZ zPAn+M$xH@Eg??FH3R=ABLc$N8EkU7HP?VpXT3ifF61h2gaGBi1%sg$d@xbuHVlya( zk!CeCxq#9pBBj8s&O?FD!}+a0vM5w(2hNOAoP|2V;3p2pld`=1PF~M ZnXo2_0B=?{kRoOv+zF&ZfW;sK0|33V&Bg!# literal 0 HcmV?d00001 diff --git a/FurnitureAssembly/FurnitureAssemblyRestApi/Program.cs b/FurnitureAssembly/FurnitureAssemblyRestApi/Program.cs index 4297a7b..a3bae35 100644 --- a/FurnitureAssembly/FurnitureAssemblyRestApi/Program.cs +++ b/FurnitureAssembly/FurnitureAssemblyRestApi/Program.cs @@ -6,6 +6,7 @@ using FurnitureAssemblyContracts.StorageContracts; using FurnitureAssemblyDatabaseImplement.Implements; using Microsoft.OpenApi.Models; using FurnitureAssemblyBusinessLogic.MailWorker; +using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile; var builder = WebApplication.CreateBuilder(args); @@ -33,12 +34,18 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); + +builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); + builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/FurnitureAssembly/FurnitureAssemblyRestApi/pdf_storekeeper.pdf b/FurnitureAssembly/FurnitureAssemblyRestApi/pdf_storekeeper.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5a039bb23ef26c237a9edce2915f5f651ecaa01b GIT binary patch literal 26141 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 U`y)RBm}(|U%+7vCO`iDw0nJ4aZU6uP literal 0 HcmV?d00001 diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/APIClient.cs b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/APIClient.cs index da40b26..02ad713 100644 --- a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/APIClient.cs +++ b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/APIClient.cs @@ -31,14 +31,22 @@ namespace FurnitureAssemblyStoreKeeperClientApp } public static void PostRequest(string requestUrl, T model) { - var json = JsonConvert.SerializeObject(model); - var data = new StringContent(json, Encoding.UTF8, "application/json"); - var response = _client.PostAsync(requestUrl, data); - var result = response.Result.Content.ReadAsStringAsync().Result; - if (!response.Result.IsSuccessStatusCode) + try { - throw new Exception(result); + var json = JsonConvert.SerializeObject(model); + var data = new StringContent(json, Encoding.UTF8, "application/json"); + var response = _client.PostAsync(requestUrl, data); + var result = response.Result.Content.ReadAsStringAsync().Result; + if (!response.Result.IsSuccessStatusCode) + { + throw new Exception(result); + } } + catch (TaskCanceledException ex ) + { + + } + } } } diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Controllers/HomeController.cs b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Controllers/HomeController.cs index da3f013..3fbaa3a 100644 --- a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Controllers/HomeController.cs +++ b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Controllers/HomeController.cs @@ -1,4 +1,5 @@ -using FurnitureAssemblyContracts.BindingModels; +using FurnitureAssemblyBusinessLogic.BusinessLogics; +using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.SearchModels; using FurnitureAssemblyContracts.StorageContracts; using FurnitureAssemblyContracts.ViewModels; @@ -13,10 +14,12 @@ namespace FurnitureAssemblyStoreKeeperClientApp.Controllers { private readonly ILogger _logger; private readonly IFurnitureStorage _furnitureStorage; - public HomeController(ILogger logger, IFurnitureStorage furnitureStorage) + private readonly IReportStorekeeperLogic _report; + public HomeController(ILogger logger, IFurnitureStorage furnitureStorage, IReportStorekeeperLogic report) { _logger = logger; _furnitureStorage = furnitureStorage; + _report = report; } public IActionResult Index() @@ -416,5 +419,159 @@ namespace FurnitureAssemblyStoreKeeperClientApp.Controllers Response.Redirect("GetFurnitureList"); } #endregion + + #region Reports + [HttpGet] + public IActionResult CreateReport() + { + if (APIClient.User == null) + { + return Redirect("~/Home/Enter"); + } + return View(_furnitureStorage.GetFullList()); + } + + public void CreateReport(int[] setIds, string type) + { + if (APIClient.User == null) + { + throw new Exception("Вы как суда попали? Суда вход только авторизованным"); + } + if (string.IsNullOrEmpty(type)) + { + throw new Exception("Неверный тип отчета"); + } + if (type == "docx") + { + //_reportStorekeeper.SaveFurnituresToWordFile(new ReportBindingModel + //{ + // FileName = "DocFile", + // Ids = setIds, + //}); + APIClient.PostRequest("api/ReportStorekeeper/CreateReportToDocx", new ReportBindingModel + { + FileName = "DocFile", + Ids = setIds, + }); + Response.Redirect("GetDocxFile"); + } + else + { + _report.SaveFurnituresToExelFile(new ReportBindingModel + { + FileName = "ExelFile", + Ids = setIds, + }); + //APIClient.PostRequest("api/ReportStorekeeper/SaveFurnituresToExelFile", new ReportBindingModel + //{ + // FileName = "ExelFile", + // Ids = setIds, + //}); + Response.Redirect("GetXlsxFile"); + } + } + + [HttpGet] + public IActionResult GetDocxFile() + { + return new PhysicalFileResult("C:\\temp\\word_storekeeper.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + } + public IActionResult GetXlsxFile() + { + return new PhysicalFileResult("C:\\temp\\excel_storekeeper.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + } + + public IActionResult CreateListMaterials() + { + if (APIClient.User == null) + { + return Redirect("~/Home/Enter"); + } + return View(); + } + [HttpPost] + public void CreateListMaterials(DateTime dateFrom, DateTime dateTo, string customerEmail) + { + if (APIClient.User == null) + { + throw new Exception("Вы как суда попали? Суда вход только авторизованным"); + } + if (string.IsNullOrEmpty(customerEmail)) + { + throw new Exception("Email пуст"); + } + APIClient.PostRequest("api/reportStorekeeper/CreateReportOrdersToPdf", new ReportBindingModel + { + FileName = "pdf_storekeeper.pdf", + DateFrom = dateFrom.ToUniversalTime(), + DateTo = dateTo.ToUniversalTime(), + }); + APIClient.PostRequest("api/reportStorekeeper/sendpdftomail", new MailSendInfoBindingModel + { + MailAddress = customerEmail, + Subject = "Отчет по заказам", + Text = "Отчет по заказам с " + dateFrom.ToShortDateString() + " до " + dateTo.ToShortDateString() + }); + + Response.Redirect("OrdersReport"); + } + [HttpGet] + public string GetMaterialReport(DateTime dateFrom, DateTime dateTo) + { + if (APIClient.User == null) + { + throw new Exception("Вы как суда попали? Суда вход только авторизованным"); + } + List result; + try + { + result = _report.GetOrders(new ReportBindingModel + { + DateFrom = dateFrom, + DateTo = dateTo + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка создания отчета"); + throw; + } + if (result == null) + { + return "error"; + } + string html = ""; + //html += $"

{report.MaterialName}

"; + html += $""; + html += ""; + html += ""; + html += $""; + html += $""; + html += ""; + html += ""; + + html += ""; + double sum = 0; + foreach (var report in result) + { + int i = 1; + sum += report.Sum; + html += ""; + html += $""; + html += $""; + html += $""; + html += ""; + i++; + } + html += ""; + html += "
МатериалСумма
{i}{report.MaterialName}{report.Sum}
"; + html += $"

Итого: {sum}

"; + return html; + } + public IActionResult GetPdfFile() + { + return new PhysicalFileResult("C:\\temp\\pdf_storekeeper.pdf", "application/pdf"); + } + #endregion } } \ No newline at end of file diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/ExelFile b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/ExelFile new file mode 100644 index 0000000000000000000000000000000000000000..44180d05354e6f17e51947fcaefb0f8c534b54b0 GIT binary patch literal 2958 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 literal 0 HcmV?d00001 diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/FurnitureAssemblyStoreKeeperClientApp.csproj b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/FurnitureAssemblyStoreKeeperClientApp.csproj index 43a9620..0b4b22f 100644 --- a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/FurnitureAssemblyStoreKeeperClientApp.csproj +++ b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/FurnitureAssemblyStoreKeeperClientApp.csproj @@ -11,6 +11,7 @@ + diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Program.cs b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Program.cs index 23f68cf..72db3ad 100644 --- a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Program.cs +++ b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Program.cs @@ -1,3 +1,6 @@ +using FurnitureAssemblyBusinessLogic.BusinessLogics; +using FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper; +using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile; using FurnitureAssemblyContracts.StorageContracts; using FurnitureAssemblyDatabaseImplement.Implements; using FurnitureAssemblyStoreKeeperClientApp; @@ -8,6 +11,11 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.AddTransient (); +builder.Services.AddTransient (); + +builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); var app = builder.Build(); APIClient.Connect(builder.Configuration); diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateListMaterials.cshtml b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateListMaterials.cshtml new file mode 100644 index 0000000..bc49bcd --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateListMaterials.cshtml @@ -0,0 +1,60 @@ +@using FurnitureAssemblyContracts.ViewModels + +@{ + ViewData["Title"] = "Отчет по материалам"; +} +
+

Отчет по материалам

+
+ +
+ @{ +
+
+
+ + +
+
+ + +
+
+
+ Ваш email + + +
+
+
+
+ + } +
+ +@section Scripts { + +} \ No newline at end of file diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateReport.cshtml b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateReport.cshtml new file mode 100644 index 0000000..db3c96c --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Home/CreateReport.cshtml @@ -0,0 +1,77 @@ +@using FurnitureAssemblyContracts.ViewModels + +@model List + +@{ + ViewData["Title"] = "Формирование списка"; +} + +
+

Мебель и материалы

+
+ +
+ @{ + if (Model == null) + { +

Авторизируйтесь

+ return; + } + + +
+
+
+ + +
+
+ + +
+
+ + + + + + + + + + + @foreach (var item in Model) + { + + + + + + + } + +
+ + + Название + + Стоимость + + Дата создания +
+ + + @Html.DisplayFor(modelItem => item.Name) + + @Html.DisplayFor(modelItem => item.Cost) + + @Html.DisplayFor(modelItem => item.DateCreate) +
+ +
+ } +
\ No newline at end of file diff --git a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Shared/_Layout.cshtml b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Shared/_Layout.cshtml index 7d3fd94..b8fd386 100644 --- a/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Shared/_Layout.cshtml +++ b/FurnitureAssembly/FurnitureAssemblyStoreKeeperClientApp/Views/Shared/_Layout.cshtml @@ -40,7 +40,10 @@ Области применения +