Merge branch 'Dozorova'

This commit is contained in:
DozorovaA.A 2023-05-20 02:45:13 +04:00
commit a4e276a26d
120 changed files with 77049 additions and 21 deletions

View File

@ -15,7 +15,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FurnitureAssemblyBusinessLo
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FurnitureAssemblyRestApi", "FurnitureAssemblyRestApi\FurnitureAssemblyRestApi.csproj", "{61874779-CE96-475E-A17B-69F86C1C5A85}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FurnitureAssemblyRestApi", "FurnitureAssemblyRestApi\FurnitureAssemblyRestApi.csproj", "{61874779-CE96-475E-A17B-69F86C1C5A85}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FurnitureAssemblyWorkerClientApp", "FurnitureAssemblyWorkerClientApp\FurnitureAssemblyWorkerClientApp.csproj", "{151EC2A5-A4AC-47E6-9A53-C8F3803E392F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FurnitureAssemblyWorkerClientApp", "FurnitureAssemblyWorkerClientApp\FurnitureAssemblyWorkerClientApp.csproj", "{151EC2A5-A4AC-47E6-9A53-C8F3803E392F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FurnitureAssemblyStoreKeeperClientApp", "FurnitureAssemblyStoreKeeperClientApp\FurnitureAssemblyStoreKeeperClientApp.csproj", "{223540BB-A80B-4B9E-96D4-B17ABF9A6E5A}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -51,6 +53,10 @@ Global
{151EC2A5-A4AC-47E6-9A53-C8F3803E392F}.Debug|Any CPU.Build.0 = Debug|Any CPU {151EC2A5-A4AC-47E6-9A53-C8F3803E392F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{151EC2A5-A4AC-47E6-9A53-C8F3803E392F}.Release|Any CPU.ActiveCfg = Release|Any CPU {151EC2A5-A4AC-47E6-9A53-C8F3803E392F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{151EC2A5-A4AC-47E6-9A53-C8F3803E392F}.Release|Any CPU.Build.0 = Release|Any CPU {151EC2A5-A4AC-47E6-9A53-C8F3803E392F}.Release|Any CPU.Build.0 = Release|Any CPU
{223540BB-A80B-4B9E-96D4-B17ABF9A6E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{223540BB-A80B-4B9E-96D4-B17ABF9A6E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{223540BB-A80B-4B9E-96D4-B17ABF9A6E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{223540BB-A80B-4B9E-96D4-B17ABF9A6E5A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -0,0 +1,112 @@
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels;
using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile;
using FurnitureAssemblyContracts.BindingModels;
using FurnitureAssemblyContracts.SearchModels;
using FurnitureAssemblyContracts.StorageContracts;
using FurnitureAssemblyContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.BusinessLogics
{
public class ReportStorekeeperLogic : IReportStorekeeperLogic
{
private readonly IFurnitureStorage _furnitureStorage;
private readonly AbstractSaveToExcel _saveToExcel;
private readonly AbstractSaveToWord _saveToWord;
private readonly AbstractSaveToPdf _saveToPdf;
public ReportStorekeeperLogic(IFurnitureStorage furnitureStorage,
AbstractSaveToExcel saveToExcel, AbstractSaveToWord saveToWord, AbstractSaveToPdf saveToPdf)
{
_furnitureStorage = furnitureStorage;
_saveToExcel = saveToExcel;
_saveToWord = saveToWord;
_saveToPdf = saveToPdf;
}
public List<ReportFurnitureMaterialViewModel> GetFurnitureComponent(int[]? ids)
{
var furnitures = _furnitureStorage.GetFullList().Where(x => ids.Contains(x.Id));
if(ids == null)
{
furnitures = _furnitureStorage.GetFullList();
}
var list = new List<ReportFurnitureMaterialViewModel>();
foreach (var furniture in furnitures)
{
var record = new ReportFurnitureMaterialViewModel
{
FurnitureName = furniture.Name,
Materials = new List<Tuple<string, int>>(),
TotalCount = 0
};
foreach (var materials in furniture.FurnitureMaterials.Values)
{
record.Materials.Add(new Tuple<string, int>(materials.Item1.Name, materials.Item2));
record.TotalCount += materials.Item2;
}
list.Add(record);
}
return list;
}
public List<ReportMaterialsViewModel> GetOrders(ReportBindingModel model)
{
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<ReportMaterialsViewModel>();
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)
{
_saveToExcel.CreateReport(new ExcelStoreKeeperInfo
{
FileName = model.FileName,
Title = "Список мебели",
FurnitureMaterials = GetFurnitureComponent(model.Ids)
});
}
public void SaveFurnituresToWordFile(ReportBindingModel model)
{
_saveToWord.CreateDoc(new WordStoreKeeperInfo
{
FileName = model.FileName,
Title = "Список мебели",
FurnitureMaterialsList = GetFurnitureComponent(model.Ids)
});
}
public void SaveMaterialsToPdfFile(ReportBindingModel model)
{
_saveToPdf.CreateDoc(new PdfStoreKeeperInfo
{
FileName = model.FileName,
Title = "Список заказов",
DateFrom = model.DateFrom!.Value,
DateTo = model.DateTo!.Value,
Materials = GetOrders(model)
});
}
}
}

View File

@ -51,7 +51,9 @@ namespace FurnitureAssemblyBusinessLogic.MailWorker
objMailMessage.Body = info.Text; objMailMessage.Body = info.Text;
objMailMessage.SubjectEncoding = Encoding.UTF8; objMailMessage.SubjectEncoding = Encoding.UTF8;
objMailMessage.BodyEncoding = 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); objMailMessage.Attachments.Add(attachment);
objSmtpClient.UseDefaultCredentials = false; objSmtpClient.UseDefaultCredentials = false;

View File

@ -0,0 +1,20 @@
using FurnitureAssemblyContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels
{
public class ExcelStoreKeeperInfo
{
public string FileName { get; set; } = "C:\\temp\\excel_storekeeper.xlsx";
public string Title { get; set; } = string.Empty;
public List<ReportFurnitureMaterialViewModel> FurnitureMaterials
{
get;
set;
} = new();
}
}

View File

@ -0,0 +1,18 @@
using FurnitureAssemblyContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels
{
public class PdfStoreKeeperInfo
{
public string FileName { get; set; } = "C:\\temp\\pdf_storekeeper.pdf";
public string Title { get; set; } = string.Empty;
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public List<ReportMaterialsViewModel> Materials { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using FurnitureAssemblyContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels
{
public class WordStoreKeeperInfo
{
public string FileName { get; set; } = "C:\\temp\\word_storekeeper.docx";
public string Title { get; set; } = string.Empty;
public List<ReportFurnitureMaterialViewModel> FurnitureMaterialsList { get; set; } = new();
}
}

View File

@ -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;
/// <summary>
/// Настройка стилей для файла
/// </summary>
/// <param name="workbookpart"></param>
private static void CreateStyles(WorkbookPart workbookpart)
{
var sp = workbookpart.AddNewPart<WorkbookStylesPart>();
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);
}
/// <summary>
/// Получение номера стиля из типа
/// </summary>
/// <param name="styleInfo"></param>
/// <returns></returns>
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<SharedStringTablePart>().Any()
? _spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First()
: _spreadsheetDocument.WorkbookPart.AddNewPart<SharedStringTablePart>();
// Создаем SharedStringTable, если его нет
if (_shareStringPart.SharedStringTable == null)
{
_shareStringPart.SharedStringTable = new SharedStringTable();
}
// Создаем лист в книгу
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
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<SheetData>();
if (sheetData == null)
{
return;
}
// Ищем строку, либо добавляем ее
Row row;
if (sheetData.Elements<Row>().Where(r => r.RowIndex! == excelParams.RowIndex).Any())
{
row = sheetData.Elements<Row>().Where(r => r.RowIndex! == excelParams.RowIndex).First();
}
else
{
row = new Row() { RowIndex = excelParams.RowIndex };
sheetData.Append(row);
}
// Ищем нужную ячейку
Cell cell;
if (row.Elements<Cell>().Where(c => c.CellReference!.Value == excelParams.CellReference).Any())
{
cell = row.Elements<Cell>().Where(c => c.CellReference!.Value == excelParams.CellReference).First();
}
else
{
// Все ячейки должны быть последовательно друг за другом расположены
// нужно определить, после какой вставлять
Cell? refCell = null;
foreach (Cell rowCell in row.Elements<Cell>())
{
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<SharedStringItem>().Count() - 1).ToString());
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
cell.StyleIndex = GetStyleValue(excelParams.StyleInfo);
}
protected override void MergeCells(ExcelMergeParameters excelParams)
{
if (_worksheet == null)
{
return;
}
MergeCells mergeCells;
if (_worksheet.Elements<MergeCells>().Any())
{
mergeCells = _worksheet.Elements<MergeCells>().First();
}
else
{
mergeCells = new MergeCells();
if (_worksheet.Elements<CustomSheetView>().Any())
{
_worksheet.InsertAfter(mergeCells,
_worksheet.Elements<CustomSheetView>().First());
}
else
{
_worksheet.InsertAfter(mergeCells,
_worksheet.Elements<SheetData>().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();
}
}
}

View File

@ -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,
};
}
/// <summary>
/// Создание стилей для документа
/// </summary>
/// <param name="document"></param>
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<string> 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);
}
}
}

View File

@ -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;
/// <summary>
/// Получение типа выравнивания
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private static JustificationValues GetJustificationValues(WordJustificationType type)
{
return type switch
{
WordJustificationType.Both => JustificationValues.Both,
WordJustificationType.Center => JustificationValues.Center,
_ => JustificationValues.Left,
};
}
/// <summary>
/// Настройки страницы
/// </summary>
/// <returns></returns>
private static SectionProperties CreateSectionProperties()
{
var properties = new SectionProperties();
var pageSize = new PageSize
{
Orient = PageOrientationValues.Portrait
};
properties.AppendChild(pageSize);
return properties;
}
/// <summary>
/// Задание форматирования для абзаца
/// </summary>
/// <param name="paragraphProperties"></param>
/// <returns></returns>
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();
}
}
}

View File

@ -0,0 +1,106 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Office2010.Excel;
using DocumentFormat.OpenXml.Office2013.Excel;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperEnums;
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels;
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile
{
public abstract class AbstractSaveToExcel
{
/// <summary>
/// Создание отчета
/// </summary>
/// <param name="info"></param>
public void CreateReport(ExcelStoreKeeperInfo info)
{
CreateExcel(info);
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "A",
RowIndex = 1,
Text = info.Title,
StyleInfo = ExcelStyleInfoType.Title
});
MergeCells(new ExcelMergeParameters
{
CellFromName = "A1",
CellToName = "C1"
});
uint rowIndex = 2;
foreach (var furniture in info.FurnitureMaterials)
{
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "A",
RowIndex = rowIndex,
Text = furniture.FurnitureName,
StyleInfo = ExcelStyleInfoType.Text
});
rowIndex++;
foreach (var materials in furniture.Materials)
{
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "B",
RowIndex = rowIndex,
Text = materials.Item1,
StyleInfo = ExcelStyleInfoType.TextWithBroder
});
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "C",
RowIndex = rowIndex,
Text = materials.Item2.ToString(),
StyleInfo = ExcelStyleInfoType.TextWithBroder
});
rowIndex++;
}
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "A",
RowIndex = rowIndex,
Text = "Итого",
StyleInfo = ExcelStyleInfoType.Text
});
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "C",
RowIndex = rowIndex,
Text = furniture.TotalCount.ToString(),
StyleInfo = ExcelStyleInfoType.Text
});
rowIndex++;
}
SaveExcel(info);
}
/// <summary>
/// Создание excel-файла
/// </summary>
/// <param name="info"></param>
protected abstract void CreateExcel(ExcelStoreKeeperInfo info);
/// <summary>
/// Добавляем новую ячейку в лист
/// </summary>
/// <param name="cellParameters"></param>
protected abstract void InsertCellInWorksheet(ExcelCellParameters excelParams);
/// <summary>
/// Объединение ячеек
/// </summary>
/// <param name="mergeParameters"></param>
protected abstract void MergeCells(ExcelMergeParameters excelParams);
/// <summary>
/// Сохранение файла
/// </summary>
/// <param name="info"></param>
protected abstract void SaveExcel(ExcelStoreKeeperInfo info);
}
}

View File

@ -0,0 +1,91 @@
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperEnums;
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels;
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile
{
public abstract class AbstractSaveToPdf
{
public void CreateDoc(PdfStoreKeeperInfo info)
{
CreatePdf(info);
CreateParagraph(new PdfParagraph
{
Text = info.Title,
Style = "NormalTitle",
ParagraphAlignment = PdfParagraphAlignmentType.Center
});
CreateParagraph(new PdfParagraph
{
Text = $"с {info.DateFrom.ToShortDateString()} по {info.DateTo.ToShortDateString()}",
Style = "Normal",
ParagraphAlignment = PdfParagraphAlignmentType.Center
});
CreateRow(new PdfRowParameters
{
Texts = new List<string> { "Материал", "Стоимость" },
Style = "NormalTitle",
ParagraphAlignment = PdfParagraphAlignmentType.Center
});
double sum = 0;
foreach (var material in info.Materials)
{
//CreateParagraph(new PdfParagraph
//{
// Text = material.MaterialName,
// Style = "Normal",
// ParagraphAlignment = PdfParagraphAlignmentType.Left
//});
//CreateTable(new List<string> { "6cm", "3cm" });
sum += material.Sum;
CreateRow(new PdfRowParameters
{
Texts = new List<string> { material.MaterialName, material.Sum.ToString() },
Style = "Normal",
ParagraphAlignment = PdfParagraphAlignmentType.Left
});
}
CreateParagraph(new PdfParagraph
{
Text = $"Итого: {sum}\t",
Style = "Normal",
ParagraphAlignment = PdfParagraphAlignmentType.Left
});
SavePdf(info);
}
/// <summary>
/// Создание doc-файла
/// </summary>
/// <param name="info"></param>
protected abstract void CreatePdf(PdfStoreKeeperInfo info);
/// <summary>
/// Создание параграфа с текстом
/// </summary>
/// <param name="title"></param>
/// <param name="style"></param>
protected abstract void CreateParagraph(PdfParagraph paragraph);
/// <summary>
/// Создание таблицы
/// </summary>
/// <param name="title"></param>
/// <param name="style"></param>
protected abstract void CreateTable(List<string> columns);
/// <summary>
/// Создание и заполнение строки
/// </summary>
/// <param name="rowParameters"></param>
protected abstract void CreateRow(PdfRowParameters rowParameters);
/// <summary>
/// Сохранение файла
/// </summary>
/// <param name="info"></param>
protected abstract void SavePdf(PdfStoreKeeperInfo PdfStoreKeeperInfo);
}
}

View File

@ -0,0 +1,87 @@
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperEnums;
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels;
using FurnitureAssemblyBusinessLogic.OfficePackage.HelperModels.StorekeeperModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile
{
public abstract class AbstractSaveToWord
{
public void CreateDoc(WordStoreKeeperInfo info)
{
CreateWord(info);
CreateParagraph(new WordParagraph
{
Texts = new List<(string, WordTextProperties)> { (info.Title, new WordTextProperties { Bold = true, Size = "24", }) },
TextProperties = new WordTextProperties
{
Size = "24",
JustificationType = WordJustificationType.Center
}
});
foreach (var furniture in info.FurnitureMaterialsList)
{
CreateParagraph(new WordParagraph
{
Texts = new List<(string, WordTextProperties)>
{
(furniture.FurnitureName, new WordTextProperties { Bold = true, Size = "24", })
},
TextProperties = new WordTextProperties
{
Size = "24",
JustificationType = WordJustificationType.Both
}
});
foreach (var materials in furniture.Materials)
{
CreateParagraph(new WordParagraph
{
Texts = new List<(string, WordTextProperties)>
{
(materials.Item1 + " " + materials.Item2.ToString(), new WordTextProperties { Bold = false, Size = "20", })
},
TextProperties = new WordTextProperties
{
Size = "20",
JustificationType = WordJustificationType.Both
}
});
}
CreateParagraph(new WordParagraph
{
Texts = new List<(string, WordTextProperties)>
{
("Итого " + furniture.TotalCount.ToString(), new WordTextProperties { Bold = false, Size = "24", })
},
TextProperties = new WordTextProperties
{
Size = "24",
JustificationType = WordJustificationType.Both
}
});
}
SaveWord(info);
}
/// <summary>
/// Создание doc-файла
/// </summary>
/// <param name="info"></param>
protected abstract void CreateWord(WordStoreKeeperInfo info);
/// <summary>
/// Создание абзаца с текстом
/// </summary>
/// <param name="paragraph"></param>
/// <returns></returns>
protected abstract void CreateParagraph(WordParagraph paragraph);
/// <summary>
/// Сохранение файла
/// </summary>
/// <param name="info"></param>
protected abstract void SaveWord(WordStoreKeeperInfo info);
}
}

View File

@ -0,0 +1,17 @@
using FurnitureAssemblyContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyContracts.BindingModels
{
public class ReportBindingModel
{
public string FileName { get; set; } = string.Empty;
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
public int[]? Ids{ get; set; }
}
}

View File

@ -0,0 +1,43 @@
using FurnitureAssemblyContracts.BindingModels;
using FurnitureAssemblyContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic.BusinessLogics
{
public interface IReportStorekeeperLogic
{
/// <summary>
/// Получение списка мебели с разбиением по материалам
/// </summary>
/// <returns></returns>
List<ReportFurnitureMaterialViewModel> GetFurnitureComponent(int[]? ids);
/// <summary>
/// Получение отчета по движению материалов за период времени
/// </summary>
/// <returns></returns>
List<ReportMaterialsViewModel> GetOrders(ReportBindingModel model);
/// <summary>
/// Сохранение отчета по гарнитурам в файл-Word
/// </summary>
/// <param name="model"></param>
void SaveFurnituresToWordFile(ReportBindingModel model);
/// <summary>
/// Сохранение отчета по гарнитурам в файл-Excel
/// </summary>
/// <param name="model"></param>
void SaveFurnituresToExelFile(ReportBindingModel model);
/// <summary>
/// Сохранение отчета о материалах в файл-Pdf
/// </summary>
/// <param name="model"></param>
void SaveMaterialsToPdfFile(ReportBindingModel model);
}
}

View File

@ -11,5 +11,8 @@ namespace FurnitureAssemblyContracts.SearchModels
public int? Id { get; set; } public int? Id { get; set; }
public string? Name { get; set; } public string? Name { get; set; }
public int? UserId { get; set; } public int? UserId { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
} }
} }

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyContracts.ViewModels
{
public class ReportFurnitureMaterialViewModel
{
public string FurnitureName { get; set; } = string.Empty;
public int TotalCount { get; set; }
public List<Tuple<string, int>> Materials { get; set; } = new();
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FurnitureAssemblyContracts.ViewModels
{
public class ReportMaterialsViewModel
{
public int Id { get; set; }
public string MaterialName { get; set; } = string.Empty;
public double Sum { get; set; }
}
}

View File

@ -18,9 +18,9 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
{ {
using var context = new FurnitureAssemblyDatabase(); using var context = new FurnitureAssemblyDatabase();
return context.Furnitures return context.Furnitures
.Include(x => x.User)
.Include(x => x.Materials) .Include(x => x.Materials)
.ThenInclude(x => x.Material).ToList() .ThenInclude(x => x.Material)
.Include(x => x.User)
.Select(x => x.GetViewModel).ToList(); .Select(x => x.GetViewModel).ToList();
} }
public List<FurnitureViewModel> GetFilteredList(FurnitureSearchModel model) public List<FurnitureViewModel> GetFilteredList(FurnitureSearchModel model)
@ -44,6 +44,25 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
.Where(x => x.UserId == model.UserId) .Where(x => x.UserId == model.UserId)
.Select(x => x.GetViewModel).ToList(); .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 else
{ {
return new(); return new();
@ -71,7 +90,7 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
} }
context.Furnitures.Add(newFurniture); context.Furnitures.Add(newFurniture);
context.SaveChanges(); context.SaveChanges();
return newFurniture.GetViewModel; return context.Furnitures.Include(x => x.Materials).Include(x => x.User).FirstOrDefault(x => x.Id == newFurniture.Id)?.GetViewModel;
} }
public FurnitureViewModel? Update(FurnitureBindingModel model) public FurnitureViewModel? Update(FurnitureBindingModel model)
{ {
@ -80,7 +99,9 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
try try
{ {
var furniture = context.Furnitures var furniture = context.Furnitures
.Include(x => x.Materials)
.Include(x => x.User) .Include(x => x.User)
.ThenInclude(x => x.Role)
.FirstOrDefault(rec => rec.Id == model.Id); .FirstOrDefault(rec => rec.Id == model.Id);
if (furniture == null) if (furniture == null)
{ {
@ -90,7 +111,7 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
context.SaveChanges(); context.SaveChanges();
furniture.UpdateMaterials(context, model); furniture.UpdateMaterials(context, model);
transaction.Commit(); transaction.Commit();
return furniture.GetViewModel; return context.Furnitures.Include(x => x.Materials).Include(x => x.User).FirstOrDefault(x => x.Id == model.Id)?.GetViewModel;
} }
catch catch
{ {

View File

@ -78,6 +78,7 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
{ {
using var context = new FurnitureAssemblyDatabase(); using var context = new FurnitureAssemblyDatabase();
var material = context.Materials var material = context.Materials
.Include(x => x.Scope)
.Include(x => x.User) .Include(x => x.User)
.FirstOrDefault(x => x.Id == model.Id); .FirstOrDefault(x => x.Id == model.Id);
if (material == null) if (material == null)
@ -93,6 +94,7 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
using var context = new FurnitureAssemblyDatabase(); using var context = new FurnitureAssemblyDatabase();
var element = context.Materials var element = context.Materials
.Include(x => x.User) .Include(x => x.User)
.Include(x => x.Scope)
.FirstOrDefault(rec => rec.Id == model.Id); .FirstOrDefault(rec => rec.Id == model.Id);
if (element != null) if (element != null)
{ {

View File

@ -24,6 +24,7 @@ namespace FurnitureAssemblyDatabaseImplement.Models
[Required] [Required]
public int UserId { get; set; } public int UserId { get; set; }
public virtual User User { get; set; } public virtual User User { get; set; }
public Dictionary<int, (IMaterialModel, int)>? _furnitureMaterials = null; public Dictionary<int, (IMaterialModel, int)>? _furnitureMaterials = null;
[NotMapped] [NotMapped]
public Dictionary<int, (IMaterialModel, int)> FurnitureMaterials public Dictionary<int, (IMaterialModel, int)> FurnitureMaterials
@ -82,9 +83,11 @@ namespace FurnitureAssemblyDatabaseImplement.Models
rec.FurnitureId == model.Id).ToList(); rec.FurnitureId == model.Id).ToList();
if (furnitureMaterials != null && furnitureMaterials.Count > 0) if (furnitureMaterials != null && furnitureMaterials.Count > 0)
{ // удалили те, которых нет в модели { // удалили те, которых нет в модели
context.FurnitureMaterials.RemoveRange(furnitureMaterials.Where(rec var last = furnitureMaterials.Where(rec
=> !model.FurnitureMaterials.ContainsKey(rec.MaterialId))); => !model.FurnitureMaterials.ContainsKey(rec.MaterialId));
context.FurnitureMaterials.RemoveRange(last);
context.SaveChanges(); context.SaveChanges();
last.ToList().ForEach(l => furnitureMaterials.Remove(l));
// обновили количество у существующих записей // обновили количество у существующих записей
foreach (var updateMaterial in furnitureMaterials) foreach (var updateMaterial in furnitureMaterials)
{ {

View File

@ -21,7 +21,7 @@ namespace FurnitureAssemblyDatabaseImplement.Models
public double Cost { get; set; } public double Cost { get; set; }
[Required] [Required]
public int ScopeId { get; set; } public int ScopeId { get; set; }
public virtual Scope Scope { get; set; } public virtual Scope Scope { get; set; } = new();
[Required] [Required]
public int UserId { get; set; } public int UserId { get; set; }
public virtual User User { get; set; } public virtual User User { get; set; }
@ -58,9 +58,9 @@ namespace FurnitureAssemblyDatabaseImplement.Models
Name = Name, Name = Name,
Cost = Cost, Cost = Cost,
ScopeId = ScopeId, ScopeId = ScopeId,
ScopeName = Scope.Name, ScopeName = Scope?.Name,
UserId = UserId, UserId = UserId,
UserName = User.Name UserName = User?.Name
}; };
} }
} }

View File

@ -30,7 +30,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка получения списка мебельных модулей"); _logger.LogError(ex, "Ошибка получения списка материалов");
throw; throw;
} }
} }
@ -43,7 +43,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка получения мебельного модуля по id={Id}", Id); _logger.LogError(ex, "Ошибка получения материала по id={Id}", Id);
throw; throw;
} }
} }
@ -56,7 +56,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка создания мебельного модуля"); _logger.LogError(ex, "Ошибка создания материала");
throw; throw;
} }
} }
@ -69,7 +69,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка обновления мебельного модуля"); _logger.LogError(ex, "Ошибка обновления материала");
throw; throw;
} }
} }
@ -82,7 +82,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка удаления мебельного модуля"); _logger.LogError(ex, "Ошибка удаления материала");
throw; throw;
} }
} }

View File

@ -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<ReportController> 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;
}
}
}
}

View File

@ -30,7 +30,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка получения списка мебельных модулей"); _logger.LogError(ex, "Ошибка получения списка областей");
throw; throw;
} }
} }
@ -43,7 +43,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка получения мебельного модуля по id={Id}", Id); _logger.LogError(ex, "Ошибка получения области по id={Id}", Id);
throw; throw;
} }
} }
@ -56,7 +56,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка создания мебельного модуля"); _logger.LogError(ex, "Ошибка создания области");
throw; throw;
} }
} }
@ -69,7 +69,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка обновления мебельного модуля"); _logger.LogError(ex, "Ошибка обновления области");
throw; throw;
} }
} }
@ -82,7 +82,7 @@ namespace FurnitureAssemblyRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка удаления мебельного модуля"); _logger.LogError(ex, "Ошибка удаления области");
throw; throw;
} }
} }

Binary file not shown.

View File

@ -6,6 +6,7 @@ using FurnitureAssemblyContracts.StorageContracts;
using FurnitureAssemblyDatabaseImplement.Implements; using FurnitureAssemblyDatabaseImplement.Implements;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using FurnitureAssemblyBusinessLogic.MailWorker; using FurnitureAssemblyBusinessLogic.MailWorker;
using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -33,12 +34,18 @@ builder.Services.AddTransient<IScopeLogic, ScopeLogic>();
builder.Services.AddTransient<ISetLogic, SetLogic>(); builder.Services.AddTransient<ISetLogic, SetLogic>();
builder.Services.AddTransient<IUserLogic, UserLogic>(); builder.Services.AddTransient<IUserLogic, UserLogic>();
builder.Services.AddTransient<IReportWorkerLogic, ReportWorkerLogic>(); builder.Services.AddTransient<IReportWorkerLogic, ReportWorkerLogic>();
builder.Services.AddTransient<IReportStorekeeperLogic, ReportStorekeeperLogic>();
builder.Services.AddTransient<MailWorker, MailWorker>(); builder.Services.AddTransient<MailWorker, MailWorker>();
builder.Services.AddTransient<AbstractWorkerSaveToExcel, SaveToExcel>(); builder.Services.AddTransient<AbstractWorkerSaveToExcel, SaveToExcel>();
builder.Services.AddTransient<AbstractWorkerSaveToWord, SaveToWord>(); builder.Services.AddTransient<AbstractWorkerSaveToWord, SaveToWord>();
builder.Services.AddTransient<AbstractWorkerSaveToPdf, SaveToPdf>(); builder.Services.AddTransient<AbstractWorkerSaveToPdf, SaveToPdf>();
builder.Services.AddTransient<AbstractSaveToExcel, FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper.SaveStoreKeeperToExcel>();
builder.Services.AddTransient<AbstractSaveToWord, FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper.SaveStoreKeeperToWord>();
builder.Services.AddTransient<AbstractSaveToPdf, FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper.SaveStoreKeeperToPdf>();
builder.Services.AddControllers(); builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();

View File

@ -0,0 +1,52 @@
using FurnitureAssemblyContracts.ViewModels;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Text;
namespace FurnitureAssemblyStoreKeeperClientApp
{
public class APIClient
{
private static readonly HttpClient _client = new();
public static UserViewModel? User { get; set; } = null;
public static void Connect(IConfiguration configuration)
{
_client.BaseAddress = new Uri(configuration["IPAddress"]);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
}
public static T? GetRequest<T>(string requestUrl)
{
var response = _client.GetAsync(requestUrl);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (response.Result.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception(result);
}
}
public static void PostRequest<T>(string requestUrl, T model)
{
try
{
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 )
{
}
}
}
}

View File

@ -0,0 +1,577 @@
using FurnitureAssemblyBusinessLogic.BusinessLogics;
using FurnitureAssemblyContracts.BindingModels;
using FurnitureAssemblyContracts.SearchModels;
using FurnitureAssemblyContracts.StorageContracts;
using FurnitureAssemblyContracts.ViewModels;
using FurnitureAssemblyDataModels.Models;
using FurnitureAssemblyStoreKeeperClientApp.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace FurnitureAssemblyStoreKeeperClientApp.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IFurnitureStorage _furnitureStorage;
private readonly IReportStorekeeperLogic _report;
public HomeController(ILogger<HomeController> logger, IFurnitureStorage furnitureStorage, IReportStorekeeperLogic report)
{
_logger = logger;
_furnitureStorage = furnitureStorage;
_report = report;
}
public IActionResult Index()
{
return View();
}
[HttpPost]
public void Privacy(string login, string password, string name, int roleId)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали? Суда вход только авторизованным");
}
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(name))
{
throw new Exception("Введите логин, пароль и ФИО");
}
APIClient.PostRequest("api/user/updateuser", new UserBindingModel
{
Id = APIClient.User.Id,
Name = name,
Login = login,
Password = password,
RoleId = roleId
});
APIClient.User.Name = name;
APIClient.User.Login = login;
APIClient.User.Password = password;
APIClient.User.RoleId = roleId;
Response.Redirect("Index");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[HttpGet]
public IActionResult Enter()
{
return View();
}
[HttpPost]
public void Enter(string login, string password)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
{
throw new Exception("Введите логин и пароль");
}
APIClient.User = APIClient.GetRequest<UserViewModel>($"api/user/login?login={login}&password={password}");
if (APIClient.User == null)
{
throw new Exception("Неверный логин/пароль");
}
else if(APIClient.User.RoleName != "Кладовщик")
{
throw new Exception("Данное приложение недоступно для вашей роли");
}
Response.Redirect("Index");
}
[HttpGet]
public IActionResult Register()
{
return View(APIClient.GetRequest<List<RoleViewModel>>($"api/role/getrolelist"));
}
[HttpPost]
public void Register(string login, string password, string name, int roleid)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(name))
{
throw new Exception("Введите логин, пароль и ФИО");
}
APIClient.PostRequest("api/user/adduser", new UserBindingModel
{
Name = name,
Login = login,
Password = password,
RoleId = roleid
});
Response.Redirect("Enter");
return;
}
#region Scope
[HttpGet]
public IActionResult GetScopeList()
{
return View(APIClient.GetRequest<List<ScopeViewModel>>($"api/scope/GetScopeList"));
}
[HttpGet]
public IActionResult CreateScope()
{
return View();
}
[HttpPost]
public void CreateScope(string name)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали?");
}
if (string.IsNullOrEmpty(name))
{
throw new Exception("Название не указано");
}
APIClient.PostRequest("api/scope/addscope", new ScopeBindingModel
{
Name = name
});
Response.Redirect("GetScopeList");
}
[HttpGet]
public IActionResult UpdateScope()
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<ScopeViewModel>>($"api/scope/GetScopeList"));
}
[HttpPost]
public void UpdateScope(int scope, string name)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали?");
}
if (string.IsNullOrEmpty(name))
{
throw new Exception("Название не указано");
}
APIClient.PostRequest("api/scope/updatescope", new ScopeBindingModel
{
Id = scope,
Name = name
});
Response.Redirect("GetScopeList");
}
[HttpGet]
public IActionResult DeleteScope()
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<ScopeViewModel>>($"api/scope/GetScopeList"));
}
[HttpPost]
public void DeleteScope(int scope)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали");
}
APIClient.PostRequest("api/scope/deletescope", new ScopeViewModel
{
Id = scope,
});
Response.Redirect("GetScopeList");
}
#endregion
#region Material
[HttpGet]
public IActionResult GetMaterialsList()
{
return View(APIClient.GetRequest<List<MaterialViewModel>>($"api/material/getmateriallist"));
}
[HttpGet]
public IActionResult CreateMaterial()
{
return View();
}
[HttpPost]
public void CreateMaterial(string name, double cost, int scopeId,int UserId)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали?");
}
if (string.IsNullOrEmpty(name))
{
throw new Exception("Название не указано");
}
if (cost <= 0)
{
throw new Exception("Цена должна быть положительной");
}
APIClient.PostRequest("api/material/addmaterial", new MaterialBindingModel
{
Name = name,
Cost = cost,
ScopeId = scopeId,
UserId = UserId
});
Response.Redirect("GetMaterialsList");
}
[HttpGet]
public IActionResult UpdateMaterial()
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<MaterialViewModel>>($"api/material/GetMaterialList"));
}
[HttpPost]
public void UpdateMaterial(int material, string name, double cost, int scope, int user)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали?");
}
if (string.IsNullOrEmpty(name))
{
throw new Exception("Название не указано");
}
APIClient.PostRequest("api/material/updatematerial", new MaterialBindingModel
{
Id = material,
Name = name,
Cost = cost,
ScopeId = scope,
UserId = user
});
Response.Redirect("GetMaterialsList");
}
[HttpGet]
public IActionResult DeleteMaterial()
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<MaterialViewModel>>($"api/material/GetMaterialList"));
}
[HttpPost]
public void DeleteMaterial(int material)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали");
}
APIClient.PostRequest("api/material/deletematerial", new MaterialBindingModel
{
Id = material,
});
Response.Redirect("GetMaterialsList");
}
#endregion
#region Furniture
[HttpGet]
public IActionResult GetFurnitureList()
{
return View(_furnitureStorage.GetFullList());
//return View(APIClient.GetRequest<List<FurnitureViewModel>>($"api/furniture/getfurniturelist"));
}
[HttpGet]
public IActionResult CreateFurniture()
{
return View();
}
[HttpPost]
public double Calc(int count, int furniture)
{
var prod = APIClient.GetRequest<FurnitureViewModel>($"api/main/getfurniture?furnitureId={furniture}"
);
return count * (prod?.Cost ?? 1);
}
[HttpPost]
public void CreateFurniture(string name, int userId, int[] MaterialsIds, int[] counts)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали?");
}
if (string.IsNullOrEmpty(name))
{
throw new Exception("Название не указано");
}
if(counts == null || MaterialsIds.Length != counts.Length)
{
throw new Exception("Неверно заполнены компоненты");
}
var materials = APIClient.GetRequest<List<MaterialViewModel>>($"api/material/getmateriallist");
Dictionary<int, (IMaterialModel, int)> FurnitureMaterials = new Dictionary<int, (IMaterialModel, int)>();
double cost = 0;
for(int i = 0; i<counts.Length; i++)
{
var elem = (materials.Where(m => m.Id == MaterialsIds[i]).FirstOrDefault(), counts[i]);
FurnitureMaterials.Add(MaterialsIds[i], elem);
cost += counts[i] * materials.Where(m => m.Id == MaterialsIds[i]).FirstOrDefault().Cost;
}
_furnitureStorage.Insert(new FurnitureBindingModel
{
Name = name,
Cost = cost,
UserId = userId,
FurnitureMaterials = FurnitureMaterials,
DateCreate = DateTime.UtcNow
});
//APIClient.PostRequest("api/furniture/addfurniture", new FurnitureBindingModel
//{
// Name = name,
// Cost = cost,
// UserId = userId,
// DateCreate = DateTime.UtcNow,
// FurnitureMaterials = FurnitureMaterials
//});
Response.Redirect("GetMaterialsList");
}
[HttpGet]
public IActionResult UpdateFurniture(int id)
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
var model = _furnitureStorage.GetElement(new FurnitureSearchModel
{
Id = id
});
if(model!= null)
{
return View(model);
}
else return Redirect("~/Home/GetFurnitureList");
//var model = APIClient.GetRequest<FurnitureViewModel>($"api/furniture/GetFurniture?id={id}");
//return model != null ? View(model) : RedirectToPage("GetFurnitureList");
}
[HttpPost]
public void UpdateFurniture(int id, string name, double cost, int userId, int[] MaterialsIds, int[] counts)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали?");
}
if (string.IsNullOrEmpty(name))
{
throw new Exception("Название не указано");
}
var materials = APIClient.GetRequest<List<MaterialViewModel>>($"api/material/getmateriallist");
Dictionary<int, (IMaterialModel, int)> FurnitureMaterials = new Dictionary<int, (IMaterialModel, int)>();
double price = 0;
for (int i = 0; i < counts.Length; i++)
{
var elem = (materials.Where(m => m.Id == MaterialsIds[i]).FirstOrDefault(), counts[i]);
FurnitureMaterials.Add(MaterialsIds[i], elem);
price += elem.Item1.Cost * elem.Item2;
}
_furnitureStorage.Update(new FurnitureBindingModel
{
Id = id,
Name = name,
Cost = price,
UserId = userId,
FurnitureMaterials = FurnitureMaterials
});
Response.Redirect("GetFurnitureList");
}
[HttpGet]
public IActionResult DeleteFurniture()
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<FurnitureViewModel>>($"api/furniture/GetFurnitureList"));
}
[HttpPost]
public void DeleteFurniture(int furniture)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали");
}
APIClient.PostRequest("api/furniture/deletefurniture", new MaterialBindingModel
{
Id = furniture,
});
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<ReportMaterialsViewModel> 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 += $"<h2>{report.MaterialName}</h2>";
html += $"<table>";
html += "<thead>";
html += "<tr>";
html += $"<th>Материал</th>";
html += $"<th>Сумма</th>";
html += "</tr>";
html += "</thead>";
html += "<tbody>";
double sum = 0;
foreach (var report in result)
{
int i = 1;
sum += report.Sum;
html += "<tr>";
html += $"<td>{i}</td>";
html += $"<td>{report.MaterialName}</td>";
html += $"<td>{report.Sum}</td>";
html += "</tr>";
i++;
}
html += "</tbody>";
html += "</table>";
html += $"<h3 style=\"align-self: self-start;\">Итого: {sum}</h3>";
return html;
}
public IActionResult GetPdfFile()
{
return new PhysicalFileResult("C:\\temp\\pdf_storekeeper.pdf", "application/pdf");
}
#endregion
}
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FurnitureAssemblyBusinessLogic\FurnitureAssemblyBusinessLogic.csproj" />
<ProjectReference Include="..\FurnitureAssemblyContracts\FurnitureAssemblyContracts.csproj" />
<ProjectReference Include="..\FurnitureAssemblyDatabaseImplement\FurnitureAssemblyDatabaseImplement.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
namespace FurnitureAssemblyStoreKeeperClientApp.Models
{
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

View File

@ -0,0 +1,41 @@
using FurnitureAssemblyBusinessLogic.BusinessLogics;
using FurnitureAssemblyBusinessLogic.OfficePackage.Implements.StoreKeeper;
using FurnitureAssemblyBusinessLogic.OfficePackage.StorekeeperSaveToFile;
using FurnitureAssemblyContracts.StorageContracts;
using FurnitureAssemblyDatabaseImplement.Implements;
using FurnitureAssemblyStoreKeeperClientApp;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddTransient<IFurnitureStorage, FurnitureStorage> ();
builder.Services.AddTransient<IReportStorekeeperLogic, ReportStorekeeperLogic> ();
builder.Services.AddTransient<AbstractSaveToExcel, SaveStoreKeeperToExcel>();
builder.Services.AddTransient<AbstractSaveToPdf, SaveStoreKeeperToPdf>();
builder.Services.AddTransient<AbstractSaveToWord, SaveStoreKeeperToWord>();
var app = builder.Build();
APIClient.Connect(builder.Configuration);
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();

View File

@ -0,0 +1,28 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:30086",
"sslPort": 44344
}
},
"profiles": {
"FurnitureAssemblyStoreKeeperClientApp": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7135;http://localhost:5135",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,95 @@
@using FurnitureAssemblyContracts.ViewModels
@{
ViewData["Title"] = "Создание мебели";
var materialList = APIClient.GetRequest<List<MaterialViewModel>>($"api/material/GetMaterialList");
var userList = APIClient.GetRequest<List<UserViewModel>>($"api/user/GetUserList");
}
<div class="text-center">
<h2 class="display-4">Создание мебели</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="name" id="name" /></div>
</div>
<div class="row">
<div class="col-4">Стоимость:</div>
<div class="col-8"><input type="text" name="cost" id="cost" /></div>
<div class="row">
<div class="col-4">Изготовитель:</div>
<div class="col-8">
<select id="userId" name="userId">
<option value="0" disabled></option>
@foreach (var user in userList)
{
<option value="@user.Id">
@Html.DisplayFor(modelItem => user.Name)
</option>
}
</select>
</div>
</div>
<table class="table">
<thead>
<tr>
<th>
</th>
<th>
Название
</th>
<th>
Стоимость
</th>
<th>
Количество
</th>
</tr>
</thead>
<tbody>
@foreach (var item in materialList)
{
<tr>
<td>
<input type="checkbox" class="form-check-input" name="MaterialsIds[]" value="@item.Id" id="@item.Id">
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Cost)
</td>
<td>
<input type="text" id="@item.Id:count" name="counts[]" />
</td>
</tr>
}
</tbody>
</table>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Создать" class="btn btn-primary" /></div>
</div>
</form>
<script>
$('#furniture').on('change', function () {
check();
});
$('#count').on('change', function () {
check();
});
function check() {
var count = $('#count').val();
var furniture = $('#furniture').val();
if (count && furniture) {
$.ajax({
method: "POST",
url: "/Home/Calc",
data: { count: count, furniture: furniture },
success: function (result) {
$("#cost").val(result);}});
};
}
</script>

View File

@ -0,0 +1,60 @@
@using FurnitureAssemblyContracts.ViewModels
@{
ViewData["Title"] = "Отчет по материалам";
}
<div class="text-center">
<h1 class="display-4">Отчет по материалам</h1>
</div>
<div class="text-center">
@{
<form method="post">
<div class="mt-3">
<div class="form-check form-check-inline">
<label class="form-check-label" for="dateFrom">
От
</label>
<input type="datetime-local" id="dateFrom" name="dateFrom" />
</div>
<div class="form-check form-check-inline">
<label class="form-check-label" for="dateTo">
До
</label>
<input type="datetime-local" id="dateTo" name="dateTo" />
</div>
</div>
<div class="mt-3">
Ваш email
<input type="text" name="customerEmail" />
<button class="btn btn-primary ms-3" type="submit">Сгенерировать на почту</button>
</div>
<div class="mt-3" id="report" style="display: flex; flex-direction: column;">
</div>
</form>
<button class="btn btn-primary" type="button" id="genonform">Сгенерировать на форму</button>
}
</div>
@section Scripts {
<script>
function check() {
var dateFrom = $('#dateFrom').val();
var dateTo = $('#dateTo').val();
if (dateFrom && dateTo) {
$.ajax({
method: "GET",
url: "/Home/GetOrdersReport",
data: { dateFrom: dateFrom, dateTo: dateTo },
success: function (result) {
if (result != null) {
$('#report').html(result);
}
}
});
};
}
check();
$('#genonform').on('click', (e) => check());
</script>
}

View File

@ -0,0 +1,54 @@
@using FurnitureAssemblyContracts.ViewModels
@{
ViewData["Title"] = "Добавление материала";
var userList = APIClient.GetRequest<List<UserViewModel>>($"api/user/GetUserList");
var scopeList = APIClient.GetRequest<List<ScopeViewModel>>($"api/scope/GetScopeList");
}
<div class="text-center">
<h2 class="display-4">Добавление материала</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="name" id="name" /></div>
</div>
<div class="row">
<div class="col-4">Стоимость:</div>
<div class="col-8"><input type="text" name="cost" id="cost" /></div>
</div>
<div class="row">
<div class="col-4">Область применения:</div>
<div class="col-8">
<select name="scopeId">
<option value="0" disabled></option>
@foreach (var scope in scopeList)
{
<option value="@scope.Id">
@Html.DisplayFor(modelItem => scope.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-4">Производитель:</div>
<div class="col-8">
<select name="userID">
<option value="0" disabled></option>
@foreach (var user in userList)
{
<option value="@user.Id">
@Html.DisplayFor(modelItem => user.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Создать" class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,77 @@
@using FurnitureAssemblyContracts.ViewModels
@model List<FurnitureViewModel>
@{
ViewData["Title"] = "Формирование списка";
}
<div class="text-center">
<h1 class="display-4">Мебель и материалы</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<form method="post">
<div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="type" value="docx" id="docx">
<label class="form-check-label" for="docx">
В docx
</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="type" value="xlsx" id="xlsx" checked>
<label class="form-check-label" for="xlsx">
В xlsx
</label>
</div>
</div>
<table class="table">
<thead>
<tr>
<th>
</th>
<th>
Название
</th>
<th>
Стоимость
</th>
<th>
Дата создания
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
<input type="checkbox" class="form-check-input" name="setIds[]" value="@item.Id" id="@item.Id">
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Cost)
</td>
<td>
@Html.DisplayFor(modelItem => item.DateCreate)
</td>
</tr>
}
</tbody>
</table>
<button class="btn btn-primary" type="submit">Сгенерировать</button>
</form>
}
</div>

View File

@ -0,0 +1,18 @@
@using FurnitureAssemblyContracts.ViewModels
@{
ViewData["Title"] = "Добавление области";
}
<div class="text-center">
<h2 class="display-4">Добавление области применения</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="name" id="name" /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Создать" class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,27 @@
@using FurnitureAssemblyContracts.ViewModels;
@{
ViewData["Title"] = "Удаление мебели";
}
@model List<FurnitureViewModel>
<div class="text-center">
<h2 class="display-4">Удаление мебели</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Выбранная мебель:</div>
<div class="col-8">
<select id="furniture" name="furniture" class="form-control">
@foreach (var item in Model)
{
<option value="@item.Id">
@Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Удалить" class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,27 @@
@using FurnitureAssemblyContracts.ViewModels;
@{
ViewData["Title"] = "Удаление области";
}
@model List<MaterialViewModel>
<div class="text-center">
<h2 class="display-4">Удаление материала</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Выбранный материал:</div>
<div class="col-8">
<select id="material" name="material" class="form-control">
@foreach (var item in Model)
{
<option value="@item.Id">
@Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Удалить" class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,27 @@
@using FurnitureAssemblyContracts.ViewModels;
@{
ViewData["Title"] = "Удаление области";
}
@model List<ScopeViewModel>
<div class="text-center">
<h2 class="display-4">Удаление области применения</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Выбранная область:</div>
<div class="col-8">
<select id="scope" name="scope" class="form-control">
@foreach (var item in Model)
{
<option value="@item.Id">
@Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Удалить" class="btn btn-primary" /></div>
</div>
</form>

View File

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

View File

@ -0,0 +1,80 @@
@using FurnitureAssemblyContracts.ViewModels
@model List<FurnitureViewModel>
@{
ViewData["Title"] = "Мебель";
}
<div class="text-center">
<h1 class="display-4">Мебель</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<div>
<a asp-action="CreateFurniture">Создать</a>
<a asp-action="DeleteFurniture">Удалить</a>
</div>
<table class="table">
<thead>
<tr>
<th>
Id
</th>
<th>
Название
</th>
<th>
Стоимость
</th>
<th>
Дата создания
</th>
<th>
Изготовитель
</th>
<th>
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Id)
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Cost)
</td>
<td>
@Html.DisplayFor(modelItem => item.DateCreate)
</td>
<td>
@Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
<div class="row">
<div class="col-8"></div>
<a asp-action="UpdateFurniture" asp-route-id="@item.Id">Обновить</a>
</div>
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -0,0 +1,64 @@
@using FurnitureAssemblyContracts.ViewModels
@model List<MaterialViewModel>
@{
ViewData["Title"] = "Материалы";
}
<div class="text-center">
<h1 class="display-4">Материалы</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<div>
<a asp-action="CreateMaterial">Создать</a>
<a asp-action="UpdateMaterial">Обновить</a>
<a asp-action="DeleteMaterial">Удалить</a>
</div>
<table class="table">
<thead>
<tr>
<th>
Название
</th>
<th>
Стоимость
</th>
<th>
Область применения
</th>
<th>
Изготовитель
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Cost)
</td>
<td>
@Html.DisplayFor(modelItem => item.ScopeName)
</td>
<td>
@Html.DisplayFor(modelItem => item.UserName)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -0,0 +1,47 @@
@using FurnitureAssemblyContracts.ViewModels
@model List<ScopeViewModel>
@{
ViewData["Title"] = "Области";
}
<div class="text-center">
<h1 class="display-4">Области применения</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<div>
<a asp-action="CreateScope">Создать</a>
<a asp-action="UpdateScope">Обновить</a>
<a asp-action="DeleteScope">Удалить</a>
</div>
<table class="table">
<thead>
<tr>
<th>
Название
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -0,0 +1,8 @@
@{
ViewData["Title"] = "Домашняя страница";
}
<div class="text-center">
<h1 class="display-4">Добрый день</h1>
<p>Вас приветсвует приложение "Фабрика мебели «Мягкое место». Кладовщик"</p>
</div>

View File

@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>

View File

@ -0,0 +1,42 @@
@using FurnitureAssemblyContracts.ViewModels;
@model List<RoleViewModel>
@{
ViewData["Title"] = "Регистрация";
}
<div class="text-center">
<h2 class="display-4">Регистрация</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" /></div>
</div>
<div class="row">
<div class="col-4">ФИО:</div>
<div class="col-8"><input type="text" name="name" /></div>
</div>
<div class="row">
<div class="col-4">Роль:</div>
<div class="col-8">
<select name="roleId">
<option value="0" disabled></option>
@foreach (var role in Model)
{
<option value="@role.Id">
@Html.DisplayFor(modelItem => role.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Регистрация"
class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,99 @@
@using FurnitureAssemblyContracts.ViewModels
@model FurnitureViewModel
@{
ViewData["Title"] = "Обновление мебели";
var materialList = APIClient.GetRequest<List<MaterialViewModel>>($"api/material/GetMaterialList");
var userList = APIClient.GetRequest<List<UserViewModel>>($"api/user/GetUserList");
}
<div class="text-center">
<h2 class="display-4">Обновление мебели</h2>
</div>
<form method="post">
<div class="row" id = @Model?.Id>
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="name" id="name" value=@Model.Name /></div>
</div>
<div class="row">
<div class="col-4">Стоимость:</div>
<div class="col-8">@Html.DisplayFor(modelItem => Model.Cost)</div>
</div>
<div class="row">
<div class="col-4">Изготовитель:</div>
<div class="row">
<div class="col-8">
@Html.DisplayFor(modelItem => Model.UserName)
</div>
</div>
<table class="table">
<thead>
<tr>
<th>
</th>
<th>
Название
</th>
<th>
Стоимость
</th>
<th>
Количество
</th>
<th>
Изготовитель
</th>
</tr>
</thead>
<tbody>
@foreach (var item in materialList)
{
<tr>
<td>
@if(Model.FurnitureMaterials.Keys.Contains(item.Id))
{
<input type="checkbox" class="form-check-input" name="MaterialsIds[]" value="@item.Id" id="@item.Id" checked = true>
}
else
{
<input type="checkbox" class="form-check-input" name="MaterialsIds[]" value="@item.Id" id="@item.Id">
}
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Cost)
</td>
<td>
@if(Model.FurnitureMaterials.Keys.Contains(item.Id))
{
int count = Model.FurnitureMaterials[item.Id].Item2;
<input type="text" id="@item.Id:count" name="counts[]" value=@count />
}
else
{
<input type="text" id="@item.Id:count" name="counts[]"/>
}
</td>
<td>
@Html.DisplayFor(modelItem => item.UserName)
</td>
</tr>
}
</tbody>
</table>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Изменить" class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,67 @@
@using FurnitureAssemblyContracts.ViewModels
@model List<MaterialViewModel>
@{
ViewData["Title"] = "Изменение материала";
var scopeList = APIClient.GetRequest<List<ScopeViewModel>>($"api/scope/GetScopeList");
var userList = APIClient.GetRequest<List<UserViewModel>>($"api/user/GetUserList");
}
<div class="text-center">
<h2 class="display-4">Изменение материала</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Материал:</div>
<div class="col-8">
<select id="material" name="material" class="form-control">
@foreach (var item in Model)
{
<option value="@item.Id">
@Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="name" id="name" /></div>
</div>
<div class="row">
<div class="col-4">Стоимость:</div>
<div class="col-8"><input type="text" name="cost" id="cost" /></div>
</div>
<div class="row">
<div class="col-4">Область применения:</div>
<div class="col-8">
<select id="scope" name="scope" class="form-control">
@foreach (var item in scopeList)
{
<option value="@item.Id">
@Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-4">Производитель:</div>
<div class="col-8">
<select id="user" name="user" class="form-control">
@foreach (var item in userList)
{
<option value="@item.Id">
@Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Изменить" class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,34 @@
@using FurnitureAssemblyContracts.ViewModels
@model List<ScopeViewModel>
@{
ViewData["Title"] = "Изменение области";
}
<div class="text-center">
<h2 class="display-4">Изменение области применения</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Область применения:</div>
<div class="col-8">
<select id="scope" name="scope" class="form-control">
@foreach (var item in Model)
{
<option value="@item.Id">
@Html.DisplayFor(modelItem => item.Name)
</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="name" id="name" /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Изменить" class="btn btn-primary" /></div>
</div>
</form>

View File

@ -0,0 +1,25 @@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Фабрика мебели «Мягкое место». Кладовщик</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/FurnitureAssemblyStoreKeeperClientApp.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Фабрика мебели «Мягкое место». Кладовщик</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
@if(APIClient.User == null)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Enter">Вход</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="GetFurnitureList">Мебель</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="GetMaterialsList">Материалы</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="GetScopeList">Области применения</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="CreateReport">Отчеты</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="CreateListMaterials">Список материалов за период</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
}
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2023 - FurnitureAssemblyStoreKeeperClientApp - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>

View File

@ -0,0 +1,48 @@
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
a {
color: #0077cc;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.border-top {
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px;
}

View File

@ -0,0 +1,2 @@
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

View File

@ -0,0 +1,3 @@
@using FurnitureAssemblyStoreKeeperClientApp
@using FurnitureAssemblyStoreKeeperClientApp.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,11 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"IPAddress": "https://localhost:7181"
}

View File

@ -0,0 +1,18 @@
html {
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 60px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,4 @@
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets.
// Write your JavaScript code.

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2011-2021 Twitter, Inc.
Copyright (c) 2011-2021 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,427 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,424 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More