This commit is contained in:
dasha 2023-05-18 19:38:56 +04:00
commit 9c61562368
37 changed files with 1935 additions and 184 deletions

View File

@ -75,7 +75,7 @@ namespace HardwareShopContracts.BusinessLogicsContracts
model.PurchaseStatus = PurchaseStatus.Выдан; model.PurchaseStatus = PurchaseStatus.Выдан;
model.DatePurchase = DateTime.Now; model.DatePurchase = DateTime.Now;
CheckModel(model, false); CheckModel(model, false);
if (_purchaseStorage.Update(model) == null) if (_purchaseStorage.Update(model, false) == null)
{ {
_logger.LogWarning("Change status operation failed"); _logger.LogWarning("Change status operation failed");
return false; return false;

View File

@ -1,8 +1,15 @@
 
using HardwareShopBusinessLogic.MailWorker;
using HardwareShopBusinessLogic.OfficePackage;
using HardwareShopBusinessLogic.OfficePackage.HelperModels;
using HardwareShopBusinessLogic.OfficePackage.Implements;
using HardwareShopContracts.BindingModels; using HardwareShopContracts.BindingModels;
using HardwareShopContracts.SearchModels; using HardwareShopContracts.SearchModels;
using HardwareShopContracts.StoragesContracts; using HardwareShopContracts.StoragesContracts;
using HardwareShopContracts.ViewModels; using HardwareShopContracts.ViewModels;
using HardwareShopDatabaseImplement.Implements.Worker;
using HardwareShopDatabaseImplement.Models.Worker;
using System.Reflection.PortableExecutable;
namespace HardwareShopContracts.BusinessLogicsContracts namespace HardwareShopContracts.BusinessLogicsContracts
{ {
@ -11,10 +18,21 @@ namespace HardwareShopContracts.BusinessLogicsContracts
private readonly IPurchaseStorage _purchaseStorage; private readonly IPurchaseStorage _purchaseStorage;
public WorkerReportLogic(IPurchaseStorage purchaseStorage) private readonly AbstractSaveToExcel _saveToExcel;
{
private readonly AbstractSaveToWord _saveToWord;
private readonly AbstractSaveToPdf _saveToPdf;
private readonly AbstractMailWorker _mailKitWorker;
public WorkerReportLogic(IPurchaseStorage purchaseStorage, AbstractMailWorker mailKitWorker, AbstractSaveToPdf saveToPdf, AbstractSaveToExcel saveToExcel, AbstractSaveToWord saveToWord)
{
_purchaseStorage = purchaseStorage; _purchaseStorage = purchaseStorage;
_saveToExcel = saveToExcel;
_saveToWord = saveToWord;
_saveToPdf = saveToPdf;
_mailKitWorker = mailKitWorker;
} }
/// <summary> /// <summary>
@ -25,8 +43,10 @@ namespace HardwareShopContracts.BusinessLogicsContracts
{ {
var list = new List<ReportPurchaseComponentViewModel>(); var list = new List<ReportPurchaseComponentViewModel>();
foreach (var purchase in purchaseList) foreach (var p in purchaseList)
{ {
var purchase = _purchaseStorage.GetElement(new() { Id = p.Id })!;
var record = new ReportPurchaseComponentViewModel var record = new ReportPurchaseComponentViewModel
{ {
Id = purchase.Id, Id = purchase.Id,
@ -57,32 +77,34 @@ namespace HardwareShopContracts.BusinessLogicsContracts
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
/// <returns></returns> /// <returns></returns>
public List<ReportPurchaseViewModel> GetPurchase(ReportBindingModel model, UserBindingModel userModel) public List<ReportPurchaseViewModel> GetPurchase(ReportBindingModel model)
{ {
var list = new List<ReportPurchaseViewModel>(); var list = new List<ReportPurchaseViewModel>();
var purchases = _purchaseStorage.GetFilteredList(new PurchaseSearchModel { DateFrom = model.DateFrom, DateTo = model.DateTo, UserId = userModel.Id }); var purchases = _purchaseStorage.GetFilteredList(new PurchaseSearchModel { DateFrom = model.DateFrom, DateTo = model.DateTo, UserId = model.UserId });
foreach (var p in purchases)
foreach (var purchase in purchases)
{ {
var record = new ReportPurchaseViewModel var purchase = _purchaseStorage.GetElement(new() { Id = p.Id })!;
{ List<string> commentList = new List<string>();
Id = purchase.Id, List<string> componentList = new List<string>();
Builds = new List<(string Build, int count, List<string>, List<(string Component, int count)>)>(),
};
foreach (var build in purchase.PurchaseBuilds) foreach (var build in purchase.PurchaseBuilds)
{ {
List<string> commentList = new List<string>();
foreach (var comment in build.Value.Item1.BuildComments) foreach (var comment in build.Value.Item1.BuildComments)
{ {
commentList.Add(new(comment.Value.Text)); commentList.Add(new(comment.Value.Text));
} }
List<(string Component, int count)> componentList = new List<(string Component, int count)>();
foreach (var component in build.Value.Item1.BuildComponents) foreach (var component in build.Value.Item1.BuildComponents)
{ {
componentList.Add(new(component.Value.Item1.ComponentName, component.Value.Item2)); componentList.Add(component.Value.Item1.ComponentName);
} }
record.Builds.Add(new(build.Value.Item1.BuildName, build.Value.Item2, commentList, componentList));
} }
var record = new ReportPurchaseViewModel
{
Id = purchase.Id,
PurchaseDate = (DateTime)p.DatePurchase,
PurchaseSum = p.Sum,
Comments = commentList,
Components = componentList.Distinct().ToList()
};
list.Add(record); list.Add(record);
} }
return list; return list;
@ -93,27 +115,59 @@ namespace HardwareShopContracts.BusinessLogicsContracts
/// Сохранение компонент с указаеним покупок в файл-Word /// Сохранение компонент с указаеним покупок в файл-Word
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
public void SaveComponentsToWordFile(ReportBindingModel model) public byte[] SavePurchasesToWordFile(ReportBindingModel model, List<PurchaseViewModel> purchases)
{ {
throw new NotImplementedException(); _saveToWord.CreateBuildPurchaseReport(new WordInfo
{
FileName = model.FileName,
Title = "Список Компонентов",
PurchaseComponent = GetPurchaseComponent(purchases)
});
byte[] file = File.ReadAllBytes(model.FileName);
File.Delete(model.FileName);
return file;
} }
/// <summary> /// <summary>
/// Сохранение компонент с указаеним покупок в файл-Excel /// Сохранение компонент с указаеним покупок в файл-Excel
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
public void SaveDishComponentToExcelFile(ReportBindingModel model) public byte[] SavePurchasesToExcelFile(ReportBindingModel model, List<PurchaseViewModel> purchases)
{ {
throw new NotImplementedException(); _saveToExcel.CreatePurchaseComponentReport(new ExcelInfo
{
FileName = model.FileName,
Title = "Список Компонентов",
PurchaseComponent = GetPurchaseComponent(purchases)
});
byte[] file = File.ReadAllBytes(model.FileName);
File.Delete(model.FileName);
return file;
} }
/// <summary> /// <summary>
/// Сохранение отчёта по покупкам в файл-Pdf /// Сохранение отчёта по покупкам в файл-Pdf
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
public void SaveOrdersToPdfFile(ReportBindingModel model) public void SendByMailPurchaseReport(ReportBindingModel model)
{ {
throw new NotImplementedException(); byte[] file = _saveToPdf.GetPurchaseReportFile(new()
{
FileName = model.FileName,
Title = "Отчет по покупкам",
DateFrom = model.DateFrom,
DateTo = model.DateTo,
ReportPurchases = GetPurchase(model)
});
_mailKitWorker.MailSendAsync(new()
{
MailAddress = model.UserEmail,
Subject = "Отчет по покупкам",
Text = $"За период с {model.DateFrom.ToShortDateString()} " +
$"по {model.DateTo.ToShortDateString()}.",
File = file
});
} }
} }
} }

View File

@ -10,6 +10,7 @@
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" /> <PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
<PackageReference Include="MailKit" Version="4.0.0" /> <PackageReference Include="MailKit" Version="4.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -25,6 +25,8 @@ namespace HardwareShopBusinessLogic.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;
MemoryStream ms = new(info.File);
objMailMessage.Attachments.Add(new Attachment(ms, "report.pdf", "application/pdf"));
objSmtpClient.UseDefaultCredentials = false; objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true; objSmtpClient.EnableSsl = true;

View File

@ -56,11 +56,90 @@ namespace HardwareShopBusinessLogic.OfficePackage
SaveExcel(info); SaveExcel(info);
} }
/// <summary> /// <summary>
/// Создание excel-файла /// Создание отчета по сборкам в выбранных товарах
/// </summary> /// </summary>
/// <param name="info"></param> /// <param name="info"></param>
protected abstract void CreateExcel(ExcelInfo info); public void CreatePurchaseComponentReport(ExcelInfo info)
{
CreateExcel(info);
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "A",
RowIndex = 1,
Text = info.Title,
StyleInfo = ExcelStyleInfoType.Title
});
MergeCells(new ExcelMergeParameters
{
CellFromName = "A1",
CellToName = "E1"
});
uint rowIndex = 2;
foreach (var bg in info.PurchaseComponent)
{
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "A",
RowIndex = rowIndex,
Text = bg.Id.ToString(),
StyleInfo = ExcelStyleInfoType.Text
});
rowIndex++;
foreach (var build in bg.Builds)
{
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "B",
RowIndex = rowIndex,
Text = build.Build,
StyleInfo = ExcelStyleInfoType.TextWithBroder
});
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "C",
RowIndex = rowIndex,
Text = build.count.ToString(),
StyleInfo = ExcelStyleInfoType.TextWithBroder
});
rowIndex++;
foreach (var component in build.Item3)
{
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "D",
RowIndex = rowIndex,
Text = component.Component,
StyleInfo = ExcelStyleInfoType.TextWithBroder
});
InsertCellInWorksheet(new ExcelCellParameters
{
ColumnName = "E",
RowIndex = rowIndex,
Text = component.count.ToString(),
StyleInfo = ExcelStyleInfoType.TextWithBroder
});
rowIndex++;
}
}
rowIndex++;
}
SaveExcel(info);
}
/// <summary>
/// Создание excel-файла
/// </summary>
/// <param name="info"></param>
protected abstract void CreateExcel(ExcelInfo info);
/// <summary> /// <summary>
/// Добавляем новую ячейку в лист /// Добавляем новую ячейку в лист

View File

@ -0,0 +1,119 @@
using DocumentFormat.OpenXml.EMMA;
using HardwareShopBusinessLogic.OfficePackage.HelperEnums;
using HardwareShopBusinessLogic.OfficePackage.HelperModels;
using MigraDoc.Rendering;
namespace HardwareShopBusinessLogic.OfficePackage
{
public abstract class AbstractSaveToPdf
{
public byte[] GetPurchaseReportFile(PdfInfo 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
});
CreateTable(new List<string> { "5cm", "5cm", "5cm", "5cm", "5cm" });
CreateRow(new PdfRowParameters
{
Texts = new List<string> { "Покупка", "Дата покупки", "Цена", "Комментарии", "Комплектующие" },
Style = "NormalTitle",
ParagraphAlignment = PdfParagraphAlignmentType.Center
});
foreach (var record in info.ReportPurchases)
{
List<string> comments = record.Comments;
List<string> components = record.Components;
int recordHeight = Math.Max(comments.Count + 1, components.Count + 1);
for (int i = 0; i < recordHeight; i++)
{
List<string> cellsData = new() { "", "", "", "", "" };
if (i == 0)
{
cellsData[0] = record.Id.ToString();
cellsData[1] = record.PurchaseDate.ToShortDateString();
cellsData[2] = record.PurchaseSum.ToString("0.00") + " р.";
CreateRow(new PdfRowParameters
{
Texts = cellsData,
Style = "Normal",
ParagraphAlignment = PdfParagraphAlignmentType.Left
});
continue;
}
int k = i - 1;
if (k < comments.Count)
{
cellsData[3] = comments[k];
}
if (k < components.Count)
{
cellsData[4] = components[k];
}
CreateRow(new PdfRowParameters
{
Texts = cellsData,
Style = "Normal",
ParagraphAlignment = PdfParagraphAlignmentType.Left
});
}
}
return GetFile(info);
}
/// <summary>
/// Создание doc-файла
/// </summary>
/// <param name="info"></param>
protected abstract void CreatePdf(PdfInfo 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(PdfInfo info);
/// <summary>
/// Сохранение отправляем файл
/// </summary>
/// <param name="info"></param>
protected abstract byte[] GetFile(PdfInfo info);
}
}

View File

@ -57,11 +57,86 @@ namespace HardwareShopBusinessLogic.OfficePackage
SaveWord(info); SaveWord(info);
} }
/// <summary> public void CreateBuildPurchaseReport(WordInfo 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
}
});
List<WordRow> rows = new List<WordRow>();
rows.Add(new WordRow
{
Rows = new List<(string, WordTextProperties)> {
("Покупки", new WordTextProperties { Size = "24", Bold = true }),
("Сборки", new WordTextProperties { Size = "24", Bold = true }),
("Количество", new WordTextProperties { Size = "24", Bold = true }),
("Компоненты", new WordTextProperties { Size = "24", Bold = true }),
("Количество", new WordTextProperties { Size = "24", Bold = true })
}
});
var reportRecords = info.PurchaseComponent;
foreach (var reportRecord in reportRecords)
{
rows.Add(new WordRow
{
Rows = new List<(string, WordTextProperties)>
{
(reportRecord.Id.ToString(), new WordTextProperties { }),
("", new WordTextProperties { }),
("", new WordTextProperties { }),
("", new WordTextProperties { }),
("", new WordTextProperties { })
}
});
for (int i = 0; i < reportRecord.Builds.Count; i++)
{
rows.Add(new WordRow
{
Rows = new List<(string, WordTextProperties)>
{
("", new WordTextProperties { }),
(reportRecord.Builds[i].Build, new WordTextProperties { }),
(reportRecord.Builds[i].count.ToString(), new WordTextProperties { }),
("", new WordTextProperties { }),
("", new WordTextProperties { })
}
});
for(int j = 0; j < reportRecord.Builds[i].Item3.Count; j++)
{
rows.Add(new WordRow
{
Rows = new List<(string, WordTextProperties)>
{
("", new WordTextProperties { }),
("", new WordTextProperties { }),
("", new WordTextProperties { }),
(reportRecord.Builds[i].Item3[j].Component, new WordTextProperties { }),
(reportRecord.Builds[i].Item3[j].count.ToString(), new WordTextProperties { })
}
});
}
}
}
CreateTable(rows);
SaveWord(info);
}
/// <summary>
/// Создание doc-файла /// Создание doc-файла
/// </summary> /// </summary>
/// <param name="info"></param> /// <param name="info"></param>
protected abstract void CreateWord(WordInfo info); protected abstract void CreateWord(WordInfo info);
/// <summary> /// <summary>
/// Создание таблицы /// Создание таблицы

View File

@ -0,0 +1,11 @@
namespace HardwareShopBusinessLogic.OfficePackage.HelperEnums
{
public enum PdfParagraphAlignmentType
{
Center,
Left,
Rigth
}
}

View File

@ -9,5 +9,7 @@ namespace HardwareShopBusinessLogic.OfficePackage.HelperModels
public string Title { get; set; } = string.Empty; public string Title { get; set; } = string.Empty;
public List<ReportBuildGoodViewModel> BuildGood { get; set; } = new(); public List<ReportBuildGoodViewModel> BuildGood { get; set; } = new();
}
public List<ReportPurchaseComponentViewModel> PurchaseComponent { get; set; } = new();
}
} }

View File

@ -0,0 +1,20 @@

using HardwareShopContracts.ViewModels;
namespace HardwareShopBusinessLogic.OfficePackage.HelperModels
{
public class PdfInfo
{
public string FileName { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public List<ReportComponentsViewModel> ReportComponents { get; set; } = new();
public List<ReportPurchaseViewModel> ReportPurchases { get; set; } = new();
}
}

View File

@ -0,0 +1,13 @@
using HardwareShopBusinessLogic.OfficePackage.HelperEnums;
namespace HardwareShopBusinessLogic.OfficePackage.HelperModels
{
public class PdfParagraph
{
public string Text { get; set; } = string.Empty;
public string Style { get; set; } = string.Empty;
public PdfParagraphAlignmentType ParagraphAlignment { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using HardwareShopBusinessLogic.OfficePackage.HelperEnums;
namespace HardwareShopBusinessLogic.OfficePackage.HelperModels
{
public class PdfRowParameters
{
public List<string> Texts { get; set; } = new();
public string Style { get; set; } = string.Empty;
public PdfParagraphAlignmentType ParagraphAlignment { get; set; }
}
}

View File

@ -9,5 +9,7 @@ namespace HardwareShopBusinessLogic.OfficePackage.HelperModels
public string Title { get; set; } = string.Empty; public string Title { get; set; } = string.Empty;
public List<ReportBuildGoodViewModel> BuildGood { get; set; } = new(); public List<ReportBuildGoodViewModel> BuildGood { get; set; } = new();
}
public List<ReportPurchaseComponentViewModel> PurchaseComponent { get; set; } = new();
}
} }

View File

@ -0,0 +1,122 @@
using HardwareShopBusinessLogic.OfficePackage.HelperEnums;
using HardwareShopBusinessLogic.OfficePackage.HelperModels;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
namespace HardwareShopBusinessLogic.OfficePackage.Implements
{
public class SaveToPdf : 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(PdfInfo 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(PdfInfo info)
{
var renderer = new PdfDocumentRenderer(true)
{
Document = _document
};
renderer.RenderDocument();
renderer.PdfDocument.Save(info.FileName);
}
protected override byte[] GetFile(PdfInfo info)
{
SavePdf(info);
byte[] file = File.ReadAllBytes(info.FileName);
File.Delete(info.FileName);
return file;
}
}
}

View File

@ -111,7 +111,7 @@ namespace HardwareShopBusinessLogic.OfficePackage.Implements
TableGrid tableGrid = new TableGrid(); TableGrid tableGrid = new TableGrid();
for (int j = 0; j < data[0].Rows.Count; ++j) for (int j = 0; j < data[0].Rows.Count; ++j)
{ {
tableGrid.AppendChild(new GridColumn() { Width = "3200" }); tableGrid.AppendChild(new GridColumn() { Width = "1600" });
} }
table.AppendChild(tableGrid); table.AppendChild(tableGrid);
for (int i = 0; i < data.Count; ++i) for (int i = 0; i < data.Count; ++i)

View File

@ -7,5 +7,7 @@
public string Subject { get; set; } = string.Empty; public string Subject { get; set; } = string.Empty;
public string Text { get; set; } = string.Empty; public string Text { get; set; } = string.Empty;
public byte[] File { get; set; } = Array.Empty<byte>();
} }
} }

View File

@ -31,5 +31,11 @@ namespace HardwareShopContracts.BindingModels
get; get;
set; set;
} = new(); } = new();
public List<PurchaseViewModel> Purchases
{
get;
set;
} = new();
} }
} }

View File

@ -2,12 +2,14 @@
{ {
public class ReportBindingModel public class ReportBindingModel
{ {
public string UserEmail { get; set; } = string.Empty;
public string FileName { get; set; } = string.Empty; public string FileName { get; set; } = string.Empty;
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public int UserId { get; set; } public int UserId { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
} }
} }

View File

@ -17,24 +17,24 @@ namespace HardwareShopContracts.BusinessLogicsContracts
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
/// <returns></returns> /// <returns></returns>
List<ReportPurchaseViewModel> GetPurchase(ReportBindingModel model, UserBindingModel userModel); List<ReportPurchaseViewModel> GetPurchase(ReportBindingModel model);
/// <summary> /// <summary>
/// Сохранение компонент с указаеним покупок в файл-Word /// Сохранение компонент с указаеним покупок в файл-Word
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
void SaveComponentsToWordFile(ReportBindingModel model); byte[] SavePurchasesToWordFile(ReportBindingModel model, List<PurchaseViewModel> purchases);
/// <summary> /// <summary>
/// Сохранение компонент с указаеним покупок в файл-Excel /// Сохранение компонент с указаеним покупок в файл-Excel
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
void SaveDishComponentToExcelFile(ReportBindingModel model); byte[] SavePurchasesToExcelFile(ReportBindingModel model, List<PurchaseViewModel> purchases);
/// <summary> /// <summary>
/// Сохранение отчёта по покупкам в файл-Pdf /// Сохранение отчёта по покупкам в файл-Pdf
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
void SaveOrdersToPdfFile(ReportBindingModel model); void SendByMailPurchaseReport(ReportBindingModel model);
} }
} }

View File

@ -4,6 +4,8 @@
{ {
public int? Id { get; set; } public int? Id { get; set; }
public int? PurchaseId { get; set; }
public string? BuildName { get; set; } = string.Empty; public string? BuildName { get; set; } = string.Empty;
public int? UserId { get; set; } public int? UserId { get; set; }

View File

@ -11,7 +11,7 @@ namespace HardwareShopContracts.StoragesContracts
List<PurchaseViewModel> GetReportFilteredList(PurchaseSearchModel model); List<PurchaseViewModel> GetReportFilteredList(PurchaseSearchModel model);
PurchaseViewModel? GetElement(PurchaseSearchModel model); PurchaseViewModel? GetElement(PurchaseSearchModel model);
PurchaseViewModel? Insert(PurchaseBindingModel model); PurchaseViewModel? Insert(PurchaseBindingModel model);
PurchaseViewModel? Update(PurchaseBindingModel model); PurchaseViewModel? Update(PurchaseBindingModel model, bool withParams = true);
PurchaseViewModel? Delete(PurchaseBindingModel model); PurchaseViewModel? Delete(PurchaseBindingModel model);
} }
} }

View File

@ -4,6 +4,12 @@
{ {
public int Id { get; set; } public int Id { get; set; }
public List<(string Build, int count, List<string>, List<(string Component, int count)>)> Builds { get; set; } = new(); public DateTime PurchaseDate { get; set; }
public double PurchaseSum { get; set; }
public List<string> Comments { get; set; } = new();
public List<string> Components { get; set; } = new();
} }
} }

View File

@ -53,13 +53,15 @@ namespace HardwareShopDatabaseImplement.Implements.Worker
return null; return null;
} }
using var context = new HardwareShopDatabase(); using var context = new HardwareShopDatabase();
return context.Builds var dadada = context.Builds
.Include(x => x.Purchases) .Include(x => x.Purchases)
.ThenInclude(x => x.Purchase) .ThenInclude(x => x.Purchase)
.FirstOrDefault(x => (!string.IsNullOrEmpty(model.BuildName) && x.BuildName == model.BuildName) || .FirstOrDefault(x => (!string.IsNullOrEmpty(model.BuildName) && x.BuildName == model.BuildName) ||
(model.Id.HasValue && x.Id == model.Id)) (model.Id.HasValue && x.Id == model.Id))
?.GetViewModel; ?.GetViewModel;
} return dadada;
}
public BuildViewModel? Insert(BuildBindingModel model) public BuildViewModel? Insert(BuildBindingModel model)
{ {

View File

@ -80,6 +80,13 @@ namespace HardwareShopDatabaseImplement.Implements.Worker
return context.Purchases return context.Purchases
.Include(x => x.Goods) .Include(x => x.Goods)
.ThenInclude(x => x.Good) .ThenInclude(x => x.Good)
.Include(x => x.Builds)
.ThenInclude(x => x.Build)
.ThenInclude(x => x.Components)
.ThenInclude(x => x.Component)
.Include(x => x.Builds)
.ThenInclude(x => x.Build)
.ThenInclude(x => x.Comments)
.FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id) .FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)
?.GetViewModel; ?.GetViewModel;
} }
@ -101,7 +108,7 @@ namespace HardwareShopDatabaseImplement.Implements.Worker
?.GetViewModel; ?.GetViewModel;
} }
public PurchaseViewModel? Update(PurchaseBindingModel model) public PurchaseViewModel? Update(PurchaseBindingModel model, bool withParams = true)
{ {
using var context = new HardwareShopDatabase(); using var context = new HardwareShopDatabase();
using var transaction = context.Database.BeginTransaction(); using var transaction = context.Database.BeginTransaction();
@ -117,7 +124,11 @@ namespace HardwareShopDatabaseImplement.Implements.Worker
} }
purchase.Update(model); purchase.Update(model);
context.SaveChanges(); context.SaveChanges();
purchase.UpdateGoods(context, model); if (!withParams) {
transaction.Commit();
return purchase.GetViewModel;
}
purchase.UpdateGoods(context, model);
transaction.Commit(); transaction.Commit();
return purchase.GetViewModel; return purchase.GetViewModel;
} }

View File

@ -3,7 +3,10 @@ using HardwareShopContracts.BindingModels;
using HardwareShopContracts.BusinessLogicsContracts; using HardwareShopContracts.BusinessLogicsContracts;
using HardwareShopContracts.SearchModels; using HardwareShopContracts.SearchModels;
using HardwareShopContracts.ViewModels; using HardwareShopContracts.ViewModels;
using HardwareShopDatabaseImplement.Models.ManyToMany;
using HardwareShopDatabaseImplement.Models.Storekeeper;
using HardwareShopDatabaseImplement.Models.Worker; using HardwareShopDatabaseImplement.Models.Worker;
using HardwareShopDataModels.Enums;
using HardwareShopDataModels.Models; using HardwareShopDataModels.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.ComponentModel; using System.ComponentModel;
@ -16,12 +19,15 @@ namespace HardwareShopRestApi.Controllers
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IBuildLogic _buildLogic; private readonly IBuildLogic _buildLogic;
private readonly IPurchaseLogic _purchaseLogic;
public BuildController(IBuildLogic buildLogic, ILogger<UserController> logger) public BuildController(IBuildLogic buildLogic, IPurchaseLogic purchaseLogic, ILogger<UserController> logger)
{ {
_logger = logger; _logger = logger;
_buildLogic = buildLogic; _buildLogic = buildLogic;
} _purchaseLogic = purchaseLogic;
}
[HttpGet] [HttpGet]
public List<BuildViewModel>? GetBuilds(int userId = 0) public List<BuildViewModel>? GetBuilds(int userId = 0)
@ -56,7 +62,33 @@ namespace HardwareShopRestApi.Controllers
} }
} }
[HttpPost] [HttpGet]
public List<Tuple<PurchaseViewModel, int>>? GetBuildPurchase(int buildId)
{
try
{
var result = _buildLogic.ReadElement(new() { Id = buildId });
List<Tuple<PurchaseViewModel, int>> listPurchase = new List<Tuple<PurchaseViewModel, int>>();
foreach (var item in result.BuildPurchases)
{
listPurchase.Add(Tuple.Create(new PurchaseViewModel
{
Id = item.Value.Item1.Id,
Sum = item.Value.Item1.Sum,
PurchaseStatus = item.Value.Item1.PurchaseStatus,
}, item.Value.Item2));
}
return listPurchase;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка сборки");
throw;
}
}
[HttpPost]
public void Create(BuildBindingModel model) public void Create(BuildBindingModel model)
{ {
try try
@ -70,7 +102,8 @@ namespace HardwareShopRestApi.Controllers
} }
} }
[HttpPost]
[HttpPost]
public void Update(BuildBindingModel model) public void Update(BuildBindingModel model)
{ {
try try
@ -84,7 +117,138 @@ namespace HardwareShopRestApi.Controllers
} }
} }
[HttpPost] [HttpGet]
public bool LinkPurchase(int buildId, int purchaseId, int count)
{
try
{
var build = GetBuild(buildId);//APIClient.GetRequest<BuildViewModel>($"api/build/getBuild?buildId={buildId}");
var purchase = _purchaseLogic.ReadElement(new() { Id = purchaseId });
if (purchase.PurchaseStatus == PurchaseStatus.Выдан) return false;
if (build.BuildPurchases.ContainsKey(purchaseId))
{
build.BuildPurchases[purchaseId] = (purchase, build.BuildPurchases[purchaseId].Item2 + count);
}
else
{
build.BuildPurchases.Add(purchaseId, (purchase as IPurchaseModel, count));
}
Update(new BuildBindingModel
{
Id = buildId,
Price = build.Price,
BuildName = build.BuildName,
BuildPurchases = build.BuildPurchases
});
purchase.Sum = Calc(purchase.Id);
_purchaseLogic.Update(new PurchaseBindingModel
{
Id = purchase.Id,
Sum = purchase.Sum,
PurchaseStatus = purchase.PurchaseStatus,
PurchaseGoods = purchase.PurchaseGoods,
});
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка обновления данных");
throw;
}
}
private double Calc(int purchaseId)
{
var purchase = _purchaseLogic.ReadElement(new() { Id = purchaseId });
double price = 0;
foreach (var elem in purchase.PurchaseBuilds)
{
price += ((elem.Value.Item1?.Price ?? 0) * elem.Value.Item2);
}
foreach (var elem in purchase.PurchaseGoods)
{
price += ((elem.Value.Item1?.Price ?? 0) * elem.Value.Item2);
}
return Math.Round(price * 1.1, 2);
}
[HttpGet]
public bool DeleteLinkPurchase(int deleteBuildId, int deletePurchaseId)
{
try
{
var build = GetBuild(deleteBuildId);//APIClient.GetRequest<BuildViewModel>($"api/build/getBuild?buildId={buildId}");
var purchase = _purchaseLogic.ReadElement(new() { Id = deletePurchaseId });
if (purchase.PurchaseStatus == PurchaseStatus.Выдан) return false;
build.BuildPurchases.Remove(deletePurchaseId);//Add(purchaseId, (purchase as IPurchaseModel, count));
Update(new BuildBindingModel
{
Id = deleteBuildId,
Price = build.Price,
BuildName = build.BuildName,
BuildPurchases = build.BuildPurchases
});
purchase.Sum = Calc(purchase.Id);
_purchaseLogic.Update(new PurchaseBindingModel
{
Id = purchase.Id,
Sum = purchase.Sum,
PurchaseStatus = purchase.PurchaseStatus,
DatePurchase = purchase.DatePurchase,
PurchaseGoods = purchase.PurchaseGoods,
});
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка обновления данных");
throw;
}
}
[HttpGet]
public bool UpdateLinkPurchase(int updateBuildId, int updatePurchaseId, int count)
{
try
{
var build = GetBuild(updateBuildId);//APIClient.GetRequest<BuildViewModel>($"api/build/getBuild?buildId={buildId}");
var purchase = _purchaseLogic.ReadElement(new() { Id = updatePurchaseId });
if (purchase.PurchaseStatus == PurchaseStatus.Выдан) return false;
if (build.BuildPurchases.ContainsKey(updatePurchaseId))
{
build.BuildPurchases[updatePurchaseId] = (build.BuildPurchases[updatePurchaseId].Item1, count);
}
else
{
return false;
}
Update(new BuildBindingModel
{
Id = updateBuildId,
Price = build.Price,
BuildName = build.BuildName,
BuildPurchases = build.BuildPurchases
});
purchase.Sum = Calc(purchase.Id);
_purchaseLogic.Update(new PurchaseBindingModel
{
Id = purchase.Id,
Sum = purchase.Sum,
PurchaseStatus = purchase.PurchaseStatus,
DatePurchase = purchase.DatePurchase,
PurchaseGoods = purchase.PurchaseGoods,
});
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка обновления данных");
throw;
}
}
[HttpPost]
public void DeleteBuild(BuildBindingModel model) public void DeleteBuild(BuildBindingModel model)
{ {
try try

View File

@ -3,6 +3,7 @@ using HardwareShopContracts.BusinessLogicsContracts;
using HardwareShopContracts.SearchModels; using HardwareShopContracts.SearchModels;
using HardwareShopContracts.ViewModels; using HardwareShopContracts.ViewModels;
using HardwareShopDatabaseImplement.Models.Storekeeper; using HardwareShopDatabaseImplement.Models.Storekeeper;
using HardwareShopDataModels.Enums;
using HardwareShopDataModels.Models; using HardwareShopDataModels.Models;
using HardwareShopRestApi.Controllers; using HardwareShopRestApi.Controllers;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -24,6 +25,30 @@ namespace HardwareShopRestApi.Controllers
_purchaseLogic = purchaseLogic; _purchaseLogic = purchaseLogic;
} }
[HttpGet]
public Tuple<PurchaseViewModel, List<Tuple<GoodViewModel, int>>>? GetPurchaseUpdate(int purchaseId)
{
try
{
var purchase = _purchaseLogic.ReadElement(new() { Id = purchaseId });
if (purchase == null)
return null;
var tuple = Tuple.Create(purchase,
purchase.PurchaseGoods.Select(x => Tuple.Create(new GoodViewModel
{
Id = x.Value.Item1.Id,
GoodName = x.Value.Item1.GoodName,
Price = x.Value.Item1.Price
}, x.Value.Item2)).ToList());
return tuple;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения покупки");
throw;
}
}
[HttpGet] [HttpGet]
public List<PurchaseViewModel>? GetPurchases(int userId) public List<PurchaseViewModel>? GetPurchases(int userId)
{ {
@ -39,11 +64,11 @@ namespace HardwareShopRestApi.Controllers
} }
[HttpGet] [HttpGet]
public PurchaseViewModel? GetPurchase(int id) public PurchaseViewModel? GetPurchase(int purchaseId)
{ {
try try
{ {
return _purchaseLogic.ReadElement(new() { Id = id }); return _purchaseLogic.ReadElement(new() { Id = purchaseId });
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -59,8 +84,7 @@ namespace HardwareShopRestApi.Controllers
{ {
for (int i = 0; i < model.PurchaseGoodsCounts.Count; i++) for (int i = 0; i < model.PurchaseGoodsCounts.Count; i++)
{ {
model.PurchaseGoods.Add(model.ListPurchaseGoods[i].Id, model.PurchaseGoods.Add(model.ListPurchaseGoods[i].Id,(model.ListPurchaseGoods[i] as IGoodModel, model.PurchaseGoodsCounts[i]));
(model.ListPurchaseGoods[i] as IGoodModel, model.PurchaseGoodsCounts[i]));
} }
_purchaseLogic.Create(model); _purchaseLogic.Create(model);
} }
@ -72,11 +96,15 @@ namespace HardwareShopRestApi.Controllers
} }
[HttpPost] [HttpPost]
public void UpdatePurchase(PurchaseBindingModel model) public void UpdateStatusPurchase(PurchaseBindingModel model)
{ {
try try
{ {
_purchaseLogic.Update(model); var oldModel = _purchaseLogic.ReadElement(new() {
Id = model.Id,
});
model.Sum = oldModel.Sum;
_purchaseLogic.DeliveryPurchase(model);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -85,6 +113,40 @@ namespace HardwareShopRestApi.Controllers
} }
} }
[HttpPost]
public void Update(PurchaseBindingModel model)
{
try
{
for (int i = 0; i < model.PurchaseGoodsCounts.Count; i++)
{
model.PurchaseGoods.Add(model.ListPurchaseGoods[i].Id, (model.ListPurchaseGoods[i] as IGoodModel, model.PurchaseGoodsCounts[i]));
}
model.PurchaseBuilds = _purchaseLogic.ReadElement(new() { Id = model.Id }).PurchaseBuilds;
model.Sum = Calc(model);
_purchaseLogic.Update(model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка обновления данных товара");
throw;
}
}
private double Calc(PurchaseBindingModel purchase)
{
double price = 0;
foreach (var elem in purchase.PurchaseBuilds)
{
price += ((elem.Value.Item1?.Price ?? 0) * elem.Value.Item2);
}
foreach (var elem in purchase.PurchaseGoods)
{
price += ((elem.Value.Item1?.Price ?? 0) * elem.Value.Item2);
}
return Math.Round(price * 1.1, 2);
}
[HttpPost] [HttpPost]
public void DeletePurchase(PurchaseBindingModel model) public void DeletePurchase(PurchaseBindingModel model)
{ {

View File

@ -1,4 +1,5 @@
using HardwareShopContracts.BindingModels; using DocumentFormat.OpenXml.Drawing;
using HardwareShopContracts.BindingModels;
using HardwareShopContracts.BusinessLogicsContracts; using HardwareShopContracts.BusinessLogicsContracts;
using HardwareShopContracts.ViewModels; using HardwareShopContracts.ViewModels;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -75,5 +76,55 @@ namespace HardwareShopRestApi.Controllers
throw; throw;
} }
} }
[HttpPost]
public byte[] BuildPurchaseReport(PurchaseBindingModel model, string format)
{
try
{
byte[] file;
switch (format)
{
case "docx":
file = _reportWorkerLogic.SavePurchasesToWordFile(new ReportBindingModel { FileName = "temp.docx" }, model.Purchases);
break;
case "xlsx":
file = _reportWorkerLogic.SavePurchasesToExcelFile(new ReportBindingModel { FileName = "temp.xlsx" }, model.Purchases);
break;
default:
throw new FormatException("Неправильный формат файла");
}
return file;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка сохранения списка сборок по выбранным товарам");
throw;
}
}
[HttpPost]
public List<ReportPurchaseViewModel>? GetPurchaseReportData(ReportBindingModel model)
{
try
{
var report = _reportWorkerLogic.GetPurchase(model);
return report;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения данных для отчёта");
throw;
}
}
[HttpPost]
public void SendByMailPurchaseReport(ReportBindingModel reportModel)
{
_reportWorkerLogic.SendByMailPurchaseReport(reportModel);
}
} }
} }

View File

@ -38,6 +38,7 @@ builder.Services.AddTransient<IWorkerReportLogic, WorkerReportLogic>();
builder.Services.AddTransient<AbstractSaveToWord, SaveToWord>(); builder.Services.AddTransient<AbstractSaveToWord, SaveToWord>();
builder.Services.AddTransient<AbstractSaveToExcel, SaveToExcel>(); builder.Services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
builder.Services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>(); builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
builder.Services.AddControllers(); builder.Services.AddControllers();

View File

@ -46,5 +46,23 @@ namespace HardwareShopWorkerApp
throw new Exception(result); throw new Exception(result);
} }
} }
}
public static R? PostRequestWithResult<T, R>(string requestUrl, T model)
{
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = _client.PostAsync(requestUrl, data);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (response.Result.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<R>(result);
}
else
{
return default;
}
}
}
} }

View File

@ -2,10 +2,15 @@
using HardwareShopContracts.SearchModels; using HardwareShopContracts.SearchModels;
using HardwareShopContracts.ViewModels; using HardwareShopContracts.ViewModels;
using HardwareShopDatabaseImplement.Models; using HardwareShopDatabaseImplement.Models;
using HardwareShopDatabaseImplement.Models.ManyToMany;
using HardwareShopDatabaseImplement.Models.Storekeeper;
using HardwareShopDatabaseImplement.Models.Worker;
using HardwareShopDataModels.Enums; using HardwareShopDataModels.Enums;
using HardwareShopDataModels.Models;
using HardwareShopWorkerApp.Models; using HardwareShopWorkerApp.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Diagnostics; using System.Diagnostics;
using System.IO.Pipelines;
using static System.Net.Mime.MediaTypeNames; using static System.Net.Mime.MediaTypeNames;
namespace HardwareShopWorkerApp.Controllers namespace HardwareShopWorkerApp.Controllers
@ -143,7 +148,29 @@ namespace HardwareShopWorkerApp.Controllers
Response.Redirect("Builds"); Response.Redirect("Builds");
} }
[HttpGet]
public void LinkBuildPurchase(int buildId, int purchaseId, int count)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали? Суда вход только авторизованным");
}
if (buildId <= 0)
{
throw new Exception($"Идентификтаор сборки не может быть ниже или равен 0");
}
if (purchaseId <= 0)
{
throw new Exception($"Идентификтаор покупки не может быть ниже или равен 0");
}
if (count <= 0)
{
throw new Exception($"Количество сборок в покупке не может быть ниже или равен 0");
}
APIClient.GetRequest<bool>($"api/build/linkPurchase?buildId={buildId}&purchaseId={purchaseId}&count={count}");
Response.Redirect($"LinkPurchase?buildId={buildId}");
}
[HttpPost] [HttpPost]
public void DeleteBuild(int deleteBuildId) public void DeleteBuild(int deleteBuildId)
{ {
@ -262,11 +289,6 @@ namespace HardwareShopWorkerApp.Controllers
Response.Redirect("Comments"); Response.Redirect("Comments");
} }
public IActionResult listComponents()
{
return View();
}
[HttpGet] [HttpGet]
public IActionResult Purchases() public IActionResult Purchases()
{ {
@ -298,6 +320,49 @@ namespace HardwareShopWorkerApp.Controllers
return result; return result;
} }
[HttpGet]
public IActionResult ListComponents()
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
ViewBag.Purchases = APIClient.GetRequest<List<PurchaseViewModel>>($"api/purchase/getpurchases?userId={APIClient.User.Id}");
return View();
}
[HttpPost]
public int[]? ListComponents([FromBody] PurchaseBindingModel purchaseModel, [FromQuery] string format)
{
if (APIClient.User == null)
{
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным");
}
if (string.IsNullOrEmpty(format))
{
throw new FormatException($"Неправильный формат файла: {format}");
}
byte[]? file = APIClient.PostRequestWithResult<PurchaseBindingModel, byte[]>($"api/report/buildpurchasereport?format={format}", purchaseModel);
var array = file!.Select(b => (int)b).ToArray();
return array;
}
[HttpGet]
public GoodViewModel? GetPurchase(int Id)
{
if (APIClient.User == null)
{
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным");
}
var result = APIClient.GetRequest<GoodViewModel?>($"api/purchase/getpurchase?purchaseId={Id}");
if (result == null)
{
return default;
}
return result;
}
[HttpGet] [HttpGet]
public IActionResult CreatePurchase() public IActionResult CreatePurchase()
{ {
@ -324,11 +389,79 @@ namespace HardwareShopWorkerApp.Controllers
APIClient.PostRequest("api/purchase/createpurchase", purchaseModel); APIClient.PostRequest("api/purchase/createpurchase", purchaseModel);
} }
[HttpPost]
public void UpdateStatusPurchase(int id, int status)
{
if (APIClient.User == null)
{
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным");
}
if (id <= 0)
{
throw new Exception("Некорректный идентификатор");
}
if (status <= 0)
{
throw new Exception("Некорректный статус");
}
APIClient.PostRequest("api/purchase/UpdateStatusPurchase", new PurchaseBindingModel
{
Id = id,
PurchaseStatus = (PurchaseStatus)status
});
}
[HttpPost]
public void DeletePurchase(int purchaseId)
{
if (APIClient.User == null)
{
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным");
}
if (purchaseId <= 0)
{
throw new Exception("Некорректный идентификатор");
}
var purchase = APIClient.GetRequest<PurchaseViewModel>($"api/purchase/getpurchase?purchaseId={purchaseId}");
APIClient.PostRequest("api/purchase/DeletePurchase", new PurchaseBindingModel
{
Id = purchaseId,
PurchaseStatus = purchase.PurchaseStatus
});
}
[HttpGet] [HttpGet]
public IActionResult WorkerReport() public IActionResult UpdatePurchase(int purchaseId)
{ {
return View(); if (APIClient.User == null)
} {
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным");
}
ViewBag.Goods = APIClient.GetRequest<List<GoodViewModel>>($"api/good/GetAllGoods");
return View(purchaseId);
}
[HttpPost]
public void UpdatePurchase([FromBody] PurchaseBindingModel purchaseModel)
{
if (APIClient.User == null)
{
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным");
}
purchaseModel.UserId = APIClient.User.Id;
APIClient.PostRequest("api/purchase/update", purchaseModel);
}
[HttpGet]
public Tuple<PurchaseViewModel, List<Tuple<GoodViewModel?, int>>>? GetPurchaseUpdate(int purchaseId)
{
if (APIClient.User == null)
{
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным");
}
var result = APIClient.GetRequest<Tuple<PurchaseViewModel, List<Tuple<GoodViewModel?, int>>>?>($"api/purchase/getpurchaseupdate?purchaseId={purchaseId}");
return result;
}
[HttpGet] [HttpGet]
public IActionResult Builds() public IActionResult Builds()
@ -347,9 +480,90 @@ namespace HardwareShopWorkerApp.Controllers
} }
[HttpGet] [HttpGet]
public IActionResult LinkPurchase() public IActionResult LinkPurchase(int buildId)
{ {
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
if (buildId <= 0)
{
throw new Exception($"Идентификтаор сборки не может быть ниже или равен 0");
}
ViewBag.Purchase = APIClient.GetRequest<List<PurchaseViewModel>>($"api/purchase/getpurchases?userId={APIClient.User.Id}");
return View(APIClient.GetRequest<List<Tuple<PurchaseViewModel, int>>>($"api/build/GetBuildPurchase?buildId={buildId}"));
}
[HttpGet]
public void DeleteLinkPurchase(int deleteBuildId, int deletePurchaseId)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали? Суда вход только авторизованным");
}
if (deleteBuildId <= 0)
{
throw new Exception($"Идентификтаор сборки не может быть ниже или равен 0");
}
if (deletePurchaseId <= 0)
{
throw new Exception($"Идентификтаор покупки не может быть ниже или равен 0");
}
APIClient.GetRequest<bool>($"api/build/deleteLinkPurchase?deleteBuildId={deleteBuildId}&deletePurchaseId={deletePurchaseId}");
Response.Redirect($"LinkPurchase?buildId={deleteBuildId}");
}
[HttpGet]
public void UpdateLinkPurchase(int updateBuildId, int updatePurchaseId, int count)
{
if (APIClient.User == null)
{
throw new Exception("Вы как суда попали? Суда вход только авторизованным");
}
if (updateBuildId <= 0)
{
throw new Exception($"Идентификтаор сборки не может быть ниже или равен 0");
}
if (updatePurchaseId <= 0)
{
throw new Exception($"Идентификтаор покупки не может быть ниже или равен 0");
}
APIClient.GetRequest<bool>($"api/build/UpdateLinkPurchase?updateBuildId={updateBuildId}&updatePurchaseId={updatePurchaseId}&count={count}");
Response.Redirect($"LinkPurchase?buildId={updateBuildId}");
}
public IActionResult WorkerReport()
{
if (APIClient.User == null)
{
return Redirect("~/Home/Enter");
}
return View(); return View();
} }
[HttpPost]
public List<ReportPurchaseViewModel>? WorkerReport([FromBody] ReportBindingModel reportModel)
{
if (APIClient.User == null)
{
return new();
}
reportModel.UserId = APIClient.User.Id;
List<ReportPurchaseViewModel>? list = APIClient.PostRequestWithResult<ReportBindingModel, List<ReportPurchaseViewModel>>("api/report/getpurchasereportdata", reportModel);
return list;
}
[HttpPost]
public void SendByMailPurchaseReport([FromBody] ReportBindingModel reportModel)
{
if (APIClient.User == null)
{
return;
}
reportModel.UserId = APIClient.User.Id;
reportModel.UserEmail = APIClient.User.Email;
APIClient.PostRequest("api/report/SendByMailPurchaseReport", reportModel);
}
} }
} }

View File

@ -55,9 +55,7 @@
<button onclick="getBuild(@item.Id)" type="button" class="btn btn-primary btn-lg mb-5" data-bs-toggle="modal" data-bs-target="#deleteModal"> <button onclick="getBuild(@item.Id)" type="button" class="btn btn-primary btn-lg mb-5" data-bs-toggle="modal" data-bs-target="#deleteModal">
<i class="fa fa-trash" aria-hidden="true"></i> <i class="fa fa-trash" aria-hidden="true"></i>
</button> </button>
<button onclick="deleteComponent(@item.Id)" type="button" class="btn btn-danger"> <a class="btn btn-primary btn-lg mb-5" asp-controller="Home" asp-action="LinkPurchase" asp-route-buildId="@item.Id"></a>
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -24,6 +24,7 @@
<th scope="col">Товар</th> <th scope="col">Товар</th>
<th scope="col">Количество</th> <th scope="col">Количество</th>
<th scope="col">Цена</th> <th scope="col">Цена</th>
<th scope="col">Действие</th>
</tr> </tr>
</thead> </thead>
<tbody id="result"> <tbody id="result">
@ -93,12 +94,21 @@
saveBtn.addEventListener("click", () => { saveBtn.addEventListener("click", () => {
console.log('try to add purchase') console.log('try to add purchase')
console.log(list)
if (list.length == 0) {
alert('failed add good. components are empty')
return
}
let goods = [] let goods = []
let counts = [] let counts = []
list.forEach((x) => { list.forEach((x) => {
goods.push(x.good); goods.push(x.good);
counts.push(parseInt(x.count)) counts.push(parseInt(x.count))
}) })
console.log(JSON.stringify({
"Sum": parseFloat(totalSum.value),
"ListPurchaseGoods": goods, "PurchaseGoodsCounts": counts
}));
$.ajax( $.ajax(
{ {
url: `/Home/CreatePurchase`, url: `/Home/CreatePurchase`,
@ -106,7 +116,7 @@
contentType: 'application/json', contentType: 'application/json',
data: JSON.stringify({ data: JSON.stringify({
"Sum": parseFloat(totalSum.value), "Sum": parseFloat(totalSum.value),
"ListPurchaseGoods": goods "ListPurchaseGoods": goods, "PurchaseGoodsCounts": counts
}) })
} }
).done(() => window.location.href = '/Home/Purchases') ).done(() => window.location.href = '/Home/Purchases')
@ -115,12 +125,25 @@
function reloadTable() { function reloadTable() {
resultTable.innerHTML = '' resultTable.innerHTML = ''
let price = 0; let price = 0;
let count = 0;
list.forEach((elem) => { list.forEach((elem) => {
resultTable.innerHTML += `<tr><td>${elem.good.goodName}</td><td>${elem.count}</td><td>${Math.round(elem.good.price * elem.count * 100) / 100}</td><td> \
<div> \
<button onclick="deleteGood(${count})" type="button" class="btn btn-danger"> \
<i class="fa fa-trash" aria-hidden="true"></i> \
</button> \
</div><td/></tr>`
count++;
console.log(elem); console.log(elem);
resultTable.innerHTML += `<tr><td>${elem.good.goodName}</td><td>${elem.count}</td><td>${Math.round(elem.good.price * elem.count * 100) / 100}</td></tr>`
price += elem.good.price * elem.count price += elem.good.price * elem.count
}) })
totalSum.value = Math.round(price * 100) / 100 totalSum.value = Math.round(price * 110) / 100
console.log(totalSum.value);
}
function deleteGood(id) {
list = list.filter(value => value.good.goodName != resultTable.rows[id].cells[0].innerText)
reloadTable()
} }
</script> </script>

View File

@ -1,4 +1,184 @@
 @using HardwareShopContracts.ViewModels;
@model List<Tuple<PurchaseViewModel, int>>
@{
ViewData["Title"] = "Привязка сборок";
Layout = "~/Views/Shared/_LayoutWorker.cshtml";
}
<div class="text-center">
<h1 class="display-4">Привязка сборок</h1>
</div>
<div class="text-center">
@{
<p>
<button type="button" onclick="getBuild()" class="btn btn-primary btn-lg mb-5" data-bs-toggle="modal" data-bs-target="#createModal">Добавить</button>
</p>
<table class="table">
<thead>
<tr>
<th>
Идентификатор покупки
</th>
<th>
Цена
</th>
<th>
Статус
</th>
<th>
Количество сборок в заказе
</th>
<th>
Действия
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Item1.Id)
</td>
<td>
@Html.DisplayFor(modelItem => item.Item1.Sum)
</td>
<td>
@Html.DisplayFor(modelItem => item.Item1.PurchaseStatus)
</td>
<td>
@Html.DisplayFor(modelItem => item.Item2)
</td>
<td>
<div>
<button onclick="getPurchase(@item.Item1.Id)" type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updateModal">
Изменить
</button>
<button onclick="getPurchase(@item.Item1.Id)" type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">
Удалить
</button>
</div>
</td>
</tr>
}
</tbody>
</table>
}
</div>
<div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="get" asp-controller="home" asp-action="LinkBuildPurchase">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Создание сборку</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Количество</label>
<input type="number" class="form-control" required="required" name="count" />
</div>
<label class="form-label">Сборка</label>
<select id="purchaseId" name="purchaseId" class="form-control" asp-items="@(new SelectList(@ViewBag.Purchase, "Id","Id"))"></select>
</div>
<input type="hidden" id="buildId" name="buildId" />
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<input type="submit" class="btn btn-primary" value="Сохранить">
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="get" asp-controller="home" asp-action="DeleteLinkPurchase">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Удаление покупки</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div>
<div class="modal-body">
<div class="form-group">
<h1>Вы уверенны что хотите удалить сборку?</h1>
</div>
</div>
<input type="hidden" id="deleteBuildId" name="deleteBuildId" />
<input type="hidden" id="deletePurchaseId" name="deletePurchaseId" />
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<input type="submit" class="btn btn-primary" value="Удалить">
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="updateModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="get" asp-controller="home" asp-action="UpdateLinkPurchase">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Создание сборку</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Количество</label>
<input type="number" class="form-control" required="required" name="count" />
</div>
</div>
<input type="hidden" id="updateBuildId" name="updateBuildId" />
<input type="hidden" id="updatePurchaseId" name="updatePurchaseId" />
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<input type="submit" class="btn btn-primary" value="Сохранить">
</div>
</form>
</div>
</div>
</div>
@section Scripts
{
<script>
function getBuild() {
let currentUrl = window.location.href;
console.log(currentUrl);
getURLParameter(currentUrl, 'buildId');
let buildId = getURLParameter(currentUrl, 'buildId');
console.log(buildId);
$('#buildId').val(buildId);
$('#deleteBuildId').val(buildId);
$('#updateBuildId').val(buildId);
var id = document.getElementById("updateBuildId");
console.log(id.value);
}
function getURLParameter(sUrl, sParam) {
let sPageURL = sUrl.substring(sUrl.indexOf('?') + 1);
let sURLVariables = sPageURL.split('&');
for (let i = 0; i < sURLVariables.length; i++) {
let sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam) {
return sParameterName[1];
}
}
}
function getPurchase(purchaseId) {
getBuild();
$('#deletePurchaseId').val(purchaseId);
$('#updatePurchaseId').val(purchaseId);
console.log(purchaseId);
}
</script>
}
@*
@{ @{
ViewData["Title"] = "LinkPurchase"; ViewData["Title"] = "LinkPurchase";
@ -78,4 +258,4 @@
</div> </div>
</div> </div>
</div> </div>
</form> </form>*@

View File

@ -16,15 +16,14 @@
<div class="text-center"> <div class="text-center">
<h2 class="display-4">Покупки</h2> <h2 class="display-4">Покупки</h2>
<p> <p>
<a asp-controller="Home" asp-action="CreatePurchase" class="btn btn-primary mx-2">Добавить</a> <a asp-controller="Home" asp-action="CreatePurchase" class="btn btn-primary mx-2">Добавить</a>
<button type="button" class="btn btn-primary mx-2" id="delete">Удалить заказ</button> <button type="button" class="btn btn-primary mx-2" id="delete">Удалить покупку</button>
<button type="button" class="btn btn-primary mx-2" id="inwork">Выполняется</button>
<button type="button" class="btn btn-primary mx-2" id="ready">Готов</button>
<button type="button" class="btn btn-primary mx-2" id="done">Выдан</button> <button type="button" class="btn btn-primary mx-2" id="done">Выдан</button>
<button type="button" class="btn btn-primary mx-2" id="update">Обновить</button>
</p> </p>
</div> </div>
<div class="text-center" name="id"> <div class="text-center">
<table class="table"> <table class="table" id="table">
<thead> <thead>
<tr> <tr>
<th> <th>
@ -100,10 +99,8 @@
var table = document.getElementById("table"); var table = document.getElementById("table");
var remove = document.getElementById("delete"); var remove = document.getElementById("delete");
var inwork = document.getElementById("inwork");
var ready = document.getElementById("ready");
var done = document.getElementById("done"); var done = document.getElementById("done");
var order = 0; var purchase = 0;
for (var i = 1; i < table.rows.length; i++) { for (var i = 1; i < table.rows.length; i++) {
table.rows[i].onclick = function () { table.rows[i].onclick = function () {
// remove the background from the previous selected row // remove the background from the previous selected row
@ -114,46 +111,30 @@
index = this.rowIndex; index = this.rowIndex;
// add class selected to the row // add class selected to the row
this.classList.toggle("selected"); this.classList.toggle("selected");
order = parseInt(this.cells[0].innerText); purchase = parseInt(this.cells[0].innerText);
remove.addEventListener("click", () => { remove.addEventListener("click", () => {
console.log('try to delete order') console.log('try to delete purchase')
$.ajax( $.ajax(
{ {
url: `/Storekeeper/DeleteOrder`, url: `/Home/DeletePurchase`,
type: 'POST', type: 'POST',
data: { id: order } data: { purchaseId: purchase }
} }
) ).done(() => window.location.href = '/Home/Purchases')
})
inwork.addEventListener("click", () => {
console.log('try to delete order')
$.ajax(
{
url: `/Storekeeper/UpdateOrder`,
type: 'POST',
data: { id: order, status: 1 }
}
)
})
ready.addEventListener("click", () => {
console.log('try to delete order')
$.ajax(
{
url: `/Storekeeper/UpdateOrder`,
type: 'POST',
data: { id: order, status: 2 }
}
)
}) })
done.addEventListener("click", () => { done.addEventListener("click", () => {
console.log('try to delete order') console.log('try to delete purchase')
$.ajax( $.ajax(
{ {
url: `/Storekeeper/UpdateOrder`, url: `/Home/UpdateStatusPurchase`,
type: 'POST', type: 'POST',
data: { id: order, status: 3 } data: { id: purchase, status: 1 }
} }
) ).done(() => window.location.href = '/Home/Purchases')
})
update.addEventListener("click", () => {
console.log('try to update purchase')
window.location.href = '/Home/UpdatePurchase?purchaseId=' + purchase
}) })
}; };
} }

View File

@ -0,0 +1,242 @@
@using HardwareShopContracts.ViewModels
@model int
@{
ViewData["Title"] = "UpdatePurchase";
Layout = "~/Views/Shared/_LayoutWorker.cshtml";
}
<div class="text-center">
<h2 class="display-4">Редактирование покупки</h2>
</div>
<div class="d-flex flex-column align-items-center">
<div class="col-sm-3">
<label class="form-label">Цена</label>
<input type="number" step="0.01" class="form-control" name="sum" id="sum" readonly min="0.01" value="0" required>
</div>
<h1 class="display-6">Товары</h1>
<div class="d-flex justify-content-center">
<button type="button" class="btn btn-primary mx-2 mt-3" data-bs-toggle="modal" data-bs-target="#exampleModal">Добавить</button>
<button type="button" class="btn btn-primary mx-2 mt-3">Удалить</button>
</div>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Товар</th>
<th scope="col">Количество</th>
<th scope="col">Цена</th>
<th scope="col">Действие</th>
</tr>
</thead>
<tbody id="result">
</tbody>
</table>
<div class="col-sm-2 d-flex justify-content-evenly align-items-baseline">
<button type="button" class="btn btn-primary mt-3 px-4" id="createpurchase">Сохранить</button>
</div>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Товар</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div>
<div class="modal-body">
<label class="form-label">Товар</label>
<select id="good" name="good" class="form-control" asp-items="@(new SelectList(@ViewBag.Goods, "Id", "GoodName"))"></select>
<label class="form-label">Количество</label>
<input type="number" class="form-control" name="count" id="count" min="1" value="1" required>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="savegood">Сохранить</button>
</div>
</div>
</div>
</div>
@section Scripts
{
<script>
const purchaseId = @Model
let list = [];
let status;
const submitGoodBtn = document.getElementById("savegood");
//const editBtn = document.getElementById("editcomponent");
const saveBtn = document.getElementById("createpurchase");
const countElem = document.getElementById("count");
const resultTable = document.getElementById("result");
submitGoodBtn.addEventListener("click", () => {
console.log('try to add good')
var count = $('#count').val();
var good = $('#good').val();
$.ajax({
method: "GET",
url: `/Home/GetGood`,
data: { Id: good },
success: function (result) {
let flag = false
if (list.length > 0) {
list.forEach((elem) => {
if (elem.good.id === parseInt(result.id)) {
console.log('good already added')
flag = true
}
})
}
if (!flag) list.push({ good: result, count: count })
reloadTable()
countElem.value = '1'
}
});
})
saveBtn.addEventListener("click", () => {
console.log('try to add purchase')
console.log(list)
if (list.length == 0) {
alert('failed add good. components are empty')
return
}
let goods = []
let counts = []
list.forEach((x) => {
goods.push(x.good);
counts.push(parseInt(x.count))
})
console.log(JSON.stringify({
"ListPurchaseGoods": goods, "PurchaseGoodsCounts": counts
}));
$.ajax(
{
url: `/Home/UpdatePurchase`,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
"Id": purchaseId, "ListPurchaseGoods": goods, "PurchaseGoodsCounts": counts, "PurchaseStatus": status
})
}
).done(() => window.location.href = '/Home/Purchases')
.fail(function (xhr, textStatus, errorThrown) {
alert(xhr.responseText);
})
})
function reloadTable() {
resultTable.innerHTML = ''
let price = 0;
let count = 0;
list.forEach((elem) => {
resultTable.innerHTML += `<tr><td>${elem.good.goodName}</td><td>${elem.count}</td><td>${Math.round(elem.good.price * elem.count * 100) / 100}</td><td> \
<div> \
<button onclick="deleteGood(${count})" type="button" class="btn btn-danger"> \
<i class="fa fa-trash" aria-hidden="true"></i> \
</button> \
</div><td/></tr>`
count++;
console.log(elem);
})
}
function deleteGood(id) {
list = list.filter(value => value.good.goodName != resultTable.rows[id].cells[0].innerText)
reloadTable()
}
function getPurchase() {
if (purchaseId) {
$.ajax({
method: "GET",
url: "/Home/GetPurchaseUpdate",
data: { purchaseId: purchaseId },
success: function (result) {
if (result) {
console.log(result)
status = result.item1.purchaseStatus
result.item2.forEach(elem => {
list.push({ good: elem.item1, count: elem.item2 })
})
reloadTable()
}
else
alert("Ошибка получения товара")
}
})
.fail(function (xhr, textStatus, errorThrown) {
alert(xhr.responseText);
})
};
}
getPurchase();
</script>
}
@*<form class="d-flex justify-content-evenly">
<div class=" col-sm-8">
<div class="text-center">
<h2 class="display-4">Товары</h2>
</div>
<div class="text-center" name="id">
<table class="table">
<thead>
<tr>
<th>
Номер
</th>
<th>
Название товара
</th>
<th>
Цена
</th>
<th>
Количество
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div class="text-center d-flex flex-column mt-5">
<button type="button" class="btn btn-primary btn-lg mb-5" data-bs-toggle="modal" data-bs-target="#exampleModal">Добавить</button>
<button type="button" class="btn btn-primary btn-lg mb-5" data-bs-toggle="modal" data-bs-target="#exampleModal">Изменить</button>
<button type="button" class="btn btn-primary btn-lg mb-5">Удалить</button>
<button type="button" class="btn btn-primary btn-lg mb-5">Обновить</button>
<button type="button" class="btn btn-primary btn-lg mb-5">Сохранить</button>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Товар</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div>
<div class="modal-body">
<div>
<label class="form-label">Товар</label>
<select class="form-select">
<option value="1">Товар 1</option>
<option value="2">Товар 2</option>
</select>
</div>
<div>
<label class="form-label">Количество</label>
<input type="number" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<button type="button" class="btn btn-primary">Сохранить</button>
</div>
</div>
</div>
</div>
</form>
*@

View File

@ -3,13 +3,198 @@
Layout = "~/Views/Shared/_LayoutWorker.cshtml"; Layout = "~/Views/Shared/_LayoutWorker.cshtml";
} }
<form method="post" class="d-flex flex-column align-items-center"> <h4 class="fw-bold">Отчет по покупкам</h4>
<div class="col-sm-3">
<label class="form-label">С</label> <div id="error-div-shell" class="error-div-shell">
<input type="date" class="form-control" name="dateFrom"> <div>
<label class="form-label">По</label> <p id="error-p" class="error-p mb-2"></p>
<input type="date" class="form-control" name="dateTo">
</div> </div>
<button type="submit" class="btn btn-primary mt-3 px-4">Вывод на страницу</button> </div>
<button type="submit" class="btn btn-primary mt-3 px-4">Отправить на почту</button>
</form> <div class="d-flex flex-wrap gap-1 align-items-end mb-2">
<div class="mb-2">
<p class="mb-0">Дата начала:</p>
<input id="date-from-input" class="form-control" type="date" />
</div>
<div class="mb-2">
<p class="mb-0">Дата конца:</p>
<input id="date-to-input" class="form-control" type="date" />
</div>
<button id="generate-button" class="button-primary text-button mb-2">
Показать
</button>
<button id="send-by-mail-button" class="button-primary text-button mb-2">
На почту
</button>
</div>
<p class="mb-0">
<span>За период с&nbsp;</span>
<span id="date-from-span" class="fw-bold">...</span>
<span>&nbsp;по&nbsp;</span>
<span id="date-to-span" class="fw-bold">...</span>
</p>
<div class="table-shell mb-2 border">
<table class="table mb-0">
<thead class="table-head">
<tr>
<th>Номер покупки</th>
<th>Дата покупки</th>
<th>Сумма покупки</th>
<th>Комментарии</th>
<th>Комплектующие</th>
</tr>
</thead>
<tbody id="tbody">
</tbody>
</table>
</div>
@section Scripts
{
<script>
const generateButton = document.getElementById("generate-button");
const sendByMailButton = document.getElementById("send-by-mail-button");
const dateFromInput = document.getElementById("date-from-input");
const dateToInput = document.getElementById("date-to-input");
const dateFromSpan = document.getElementById("date-from-span");
const dateToSpan = document.getElementById("date-to-span");
const tbody = document.getElementById("tbody");
const errorP = document.getElementById("error-p");
const errorDivShell = document.getElementById("error-div-shell");
// [Event listeners]
generateButton.addEventListener("click", () => {
const dateFrom = new Date(dateFromInput.value);
const dateTo = new Date(dateToInput.value);
const reportModel = {
"DateFrom": dateFrom,
"DateTo": dateTo
};
if (!validate(reportModel)) {
return;
}
$.ajax({
url: "/home/WorkerReport",
type: "POST",
contentType: "application/json",
data: JSON.stringify(reportModel)
}).done((reportData) => {
dateFromSpan.innerHTML = reportModel["DateFrom"].toLocaleDateString();
dateToSpan.innerHTML = reportModel["DateTo"].toLocaleDateString();
renderTable(reportData);
});
});
sendByMailButton.addEventListener("click", () => {
const dateFrom = new Date(dateFromInput.value);
const dateTo = new Date(dateToInput.value);
const reportModel = {
"DateFrom": dateFrom,
"DateTo": dateTo
};
if (!validate(reportModel)) {
return;
}
$.ajax({
url: "/home/SendByMailPurchaseReport",
type: "POST",
contentType: "application/json",
data: JSON.stringify(reportModel)
}).done(() => {
});
});
dateFromInput.addEventListener("input", () => {
errorDivShell.style.gridTemplateRows = "0fr";
});
dateToInput.addEventListener("input", () => {
errorDivShell.style.gridTemplateRows = "0fr";
});
// ![Event listeners]
// [HTML gen]
const renderTable = function (reportData) {
tbody.innerHTML = "";
reportData.forEach((record) => {
console.log(record);
const comments = record.comments;
const components = record.components;
const recordHeight = Math.max(comments.length + 1, components.length + 1);
for (let i = 0; i < recordHeight; i++) {
let cellsData = ["", "", "", "", ""];
if (i === 0) {
cellsData[0] = record.id;
cellsData[1] = getDate(record.purchaseDate);
cellsData[2] = record.purchaseSum;
createTableRow(cellsData);
continue;
}
let k = i - 1;
if (k < comments.length) {
cellsData[3] = comments[k];
}
if (k < components.length) {
cellsData[4] = components[k];
}
createTableRow(cellsData);
}
});
}
const createTableRow = function (cellsData) {
const tr = document.createElement('tr');
tr.classList.add("table-row");
tr.appendChild(createTableCell(cellsData[0])); // Purchase
tr.appendChild(createTableCell(cellsData[1])); // DatePurchase
tr.appendChild(createTableCell(cellsData[2])); // purchaseSum
tr.appendChild(createTableCell(cellsData[3])); // Comments
tr.appendChild(createTableCell(cellsData[4])); // Copmponent
tbody.appendChild(tr);
}
const createTableCell = function (cellText) {
const td = document.createElement('td');
td.innerHTML = cellText;
return td;
}
// ![HTML gen]
// [Other]
const validate = function (reportModel) {
if (isNaN(reportModel["DateFrom"])) {
errorDivShell.style.gridTemplateRows = "1fr";
errorP.innerHTML = "Выберите начальную дату";
return false;
}
if (isNaN(reportModel["DateTo"])) {
errorDivShell.style.gridTemplateRows = "1fr";
errorP.innerHTML = "Выберите конечную дату";
return false;
}
if (reportModel["DateFrom"] >= reportModel["DateTo"]) {
errorDivShell.style.gridTemplateRows = "1fr";
errorP.innerHTML = "Начальная дата должна быть меньше конечной";
return false;
}
return true;
}
const getDate = function (iso) {
const year = iso.substring(0, 4);
const month = iso.substring(5, 7);
const day = iso.substring(8, 10);
const date = `${day}.${month}.${year}`;
return date;
}
// ![Other]
</script>
}

View File

@ -1,65 +1,153 @@
@{ @using HardwareShopContracts.ViewModels
ViewData["Title"] = "ListComponents"; @{
ViewData["Title"] = "Получение списка";
Layout = "~/Views/Shared/_LayoutWorker.cshtml"; Layout = "~/Views/Shared/_LayoutWorker.cshtml";
} }
<form method="post" class="d-flex justify-content-evenly"> <div class="text-center">
<div class=" col-sm-8"> <h1 class="display-4">Получение списка покупок</h1>
<div class="text-center"> </div>
<h2 class="display-4">Покупки</h2>
</div>
<div class="text-center" name="id">
<table class="table">
<thead>
<tr>
<th>
Номер
</th>
<th>
Дата оплаты
</th>
<th>
Сумма
</th>
<th>
Статус
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div class="text-center d-flex flex-column mt-5">
<button type="button" class="btn btn-primary btn-lg mb-5" data-bs-toggle="modal" data-bs-target="#exampleModal">Добавить</button>
<button type="button" class="btn btn-primary btn-lg mb-5">Удалить</button>
<button type="button" class="btn btn-primary btn-lg mb-5">Обновить</button>
<button type="button" class="btn btn-primary btn-lg mb-5">Сохранить в doc формате</button>
<button type="button" class="btn btn-primary btn-lg mb-5">Сохранить в xls формате</button>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="d-flex flex-column align-items-center">
<div class="modal-dialog"> <h1 class="display-6">Выбранные покупки</h1>
<div class="modal-content"> <div class="d-flex justify-content-center">
<div class="modal-header"> <button type="button" class="btn btn-primary mx-2 mt-3" data-bs-toggle="modal" data-bs-target="#exampleModal">Добавить покупку</button>
<h5 class="modal-title" id="exampleModalLabel">Покупка</h5> </div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button> <table class="table">
</div> <thead>
<div class="modal-body"> <tr>
<div> <th scope="col">Покупка</th>
<label class="form-label">Покупка</label> <th scope="col">Действия</th>
<select class="form-select"> </tr>
<option value="1">Покупка 1</option> </thead>
<option value="2">Покупка 2</option> <tbody id="result">
</select> </tbody>
</div> </table>
</div> <div class="col d-flex justify-content-evenly align-items-baseline">
<div class="modal-footer"> <button type="button" class="btn btn-primary btn-lg m-2" id="savedoc">Сохранить в doc-формате</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button> <button type="button" class="btn btn-primary btn-lg m-2" id="saveexcel">Сохранить в xls-формате</button>
<button type="button" class="btn btn-primary">Добавить</button> </div>
</div> </div>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Покупка</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div>
<div class="modal-body">
<label class="form-label">Покупка</label>
<select id="purchase" name="purchase" class="form-control" asp-items="@(new SelectList(@ViewBag.Purchases, "Id", "Id"))"></select>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="savepurchase">Сохранить</button>
</div> </div>
</div> </div>
</div> </div>
</form> </div>
@section Scripts
{
<script>
let list = [];
const submitPurchaseBtn = document.getElementById("savepurchase");
const resultTable = document.getElementById("result");
const saveDocBtn = document.getElementById("savedoc");
const saveExcelBtn = document.getElementById("saveexcel");
submitPurchaseBtn.addEventListener("click", () => {
console.log('try to add purchase')
var purchase = $('#purchase').val();
if (purchase)
$.ajax({
method: "GET",
url: `/Home/GetPurchase`,
data: { Id: purchase },
success: function (result) {
let flag = false
if (list.length > 0) {
list.forEach((elem) => {
if (elem.id === parseInt(result.id)) {
console.log('purchase already added')
flag = true
}
})
}
if (!flag) list.push(result)
reloadTable()
}
}).fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseText);
})
})
saveDocBtn.addEventListener("click", async () => {
send('docx')
})
saveExcelBtn.addEventListener("click", async () => {
send('xlsx')
})
function send(format) {
console.log(`try to save in ${format} format`)
if (list.length == 0) {
alert('operation failed. purchases or filename are empty')
return
}
$.ajax({
url: `/Home/ListComponents?format=${format}`,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ "Purchases" : list })
}).done((file) => {
let byteArray = new Uint8Array(file);
saveFile(byteArray, format);
})
.fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseText);
})
}
async function saveFile(bytes, format) {
if (window.showSaveFilePicker) {
const opts = {
suggestedName: `listcomponents.${format}`,
types: [{
description: `${format} file`,
accept:
{
[`text/${format}`]: [`.${format}`]
},
}],
};
const handle = await showSaveFilePicker(opts);
const writable = await handle.createWritable();
await writable.write(bytes);
writable.close();
alert('done')
}
}
function reloadTable() {
resultTable.innerHTML = ''
let count = 0;
list.forEach((elem) => {
resultTable.innerHTML += `<tr><td>${elem.id}</td><td> \
<div> \
<button onclick="deletePurchase(${count})" type="button" class="btn btn-danger"> \
<i class="fa fa-trash" aria-hidden="true"></i> \
</button> \
</div></td></tr>`
count++;
})
}
function deletePurchase(id) {
list = list.filter(value => value.id != resultTable.rows[id].cells[0].innerText)
reloadTable()
}
</script>
}