Compare commits
13 Commits
Task_4_Web
...
Task_6_Ema
| Author | SHA1 | Date | |
|---|---|---|---|
| 4bb1669cc6 | |||
| 5953b0e38d | |||
| ac62427ce7 | |||
| d7f59ea747 | |||
| 0b567ce757 | |||
| 559a579867 | |||
| 95456cb956 | |||
| cacd557cee | |||
| a272a6e3e6 | |||
| 0f4d9a83d3 | |||
| b96c2b1557 | |||
| 7016193611 | |||
| 5c39a434c2 |
@@ -4,21 +4,22 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YAPBusinessLogic.OfficePackage;
|
||||
using YAPContracts.BusinessLogicContracts;
|
||||
using YAPContracts.StorageContracts;
|
||||
using YAPDatabase.Implementations;
|
||||
|
||||
namespace YAPBusinessLogic.Implementations
|
||||
{
|
||||
internal class ReportBusinessLogicContract
|
||||
internal class ReportBusinessLogicContract : IReportBusinessLogicContract
|
||||
{
|
||||
private readonly ProductStorageContract _productStorageContract;
|
||||
private readonly PurchaseStorageContract _purchaseStorageContract;
|
||||
private readonly ProductSetStorageContract _productSetStorageContract;
|
||||
private readonly ComponentStorageContract _componentStorageContract;
|
||||
private readonly IProductStorageContract _productStorageContract;
|
||||
private readonly IPurchaseStorageContract _purchaseStorageContract;
|
||||
private readonly IProductSetStorageContract _productSetStorageContract;
|
||||
private readonly IComponentStorageContract _componentStorageContract;
|
||||
private readonly BasePdfBuilder _pdfBuilder;
|
||||
|
||||
|
||||
public ReportBusinessLogicContract(ProductStorageContract productStorageContract, PurchaseStorageContract purchaseStorageContract, ProductSetStorageContract productSetStorageContract, ComponentStorageContract componentStorageContract, BasePdfBuilder pdfBuilder)
|
||||
public ReportBusinessLogicContract(IProductStorageContract productStorageContract, IPurchaseStorageContract purchaseStorageContract, IProductSetStorageContract productSetStorageContract, IComponentStorageContract componentStorageContract, BasePdfBuilder pdfBuilder)
|
||||
{
|
||||
_productStorageContract = productStorageContract;
|
||||
_purchaseStorageContract = purchaseStorageContract;
|
||||
@@ -32,8 +33,7 @@ namespace YAPBusinessLogic.Implementations
|
||||
/// </summary>
|
||||
/// <param name="setsIds">Id соборок</param>
|
||||
/// <param name="format">doc/xls</param>
|
||||
/// <param name="outputPath">Пусть, куда сохранить файл</param>
|
||||
public void MakeReportProductsByProductSets(List<string> setsIds, string format, string outputPath)
|
||||
public Stream MakeReportProductsByProductSets(List<string> setsIds, string format)
|
||||
{
|
||||
// Получаем продукты по сборкам
|
||||
var products = _productStorageContract.GetListProductsByProductSet(setsIds);
|
||||
@@ -41,44 +41,45 @@ namespace YAPBusinessLogic.Implementations
|
||||
if (string.Equals(format, "xls", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var excel = new OpenXmlExcelBuilder();
|
||||
// Заголовок
|
||||
excel.AddHeader("Изделия - Сборки", 0, 4);
|
||||
// контент: изделие и под ним сборки
|
||||
excel.AddHeader("Products by Sets", 0, 4);
|
||||
|
||||
// таблица
|
||||
var rows = new List<string[]>();
|
||||
rows.Add(new[] { "Product", "Included in Sets" });
|
||||
foreach (var prod in products)
|
||||
{
|
||||
excel.AddParagraph(prod.Product.Name, 0);
|
||||
foreach (var wm in prod.Sets)
|
||||
excel.AddParagraph($" {wm.SetName}", 1);
|
||||
var setNames = prod.Sets.Any()
|
||||
? string.Join(", ", prod.Sets.Select(s => s.SetName))
|
||||
: "No Sets.";
|
||||
rows.Add(new[] { prod.Product?.Name ?? "-", setNames });
|
||||
}
|
||||
using var st = excel.Build();
|
||||
File.WriteAllBytes(outputPath, ((MemoryStream)st).ToArray());
|
||||
|
||||
excel.AddTable([10, 10], rows);
|
||||
return excel.Build();
|
||||
}
|
||||
else if (string.Equals(format, "doc", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
var word = new OpenXmlWordBuilder();
|
||||
word.AddHeader("Products by Sets");
|
||||
|
||||
// Добавляем заголовок
|
||||
word.AddHeader("Изделия - Сборки");
|
||||
|
||||
// Добавляем контент: название изделия + список сборок
|
||||
foreach (var prod in products)
|
||||
{
|
||||
word.AddParagraph(prod.Product.Name);
|
||||
foreach (var wm in prod.Sets)
|
||||
{
|
||||
word.AddParagraph($" {wm.SetName}");
|
||||
}
|
||||
word.AddParagraph($"Product: {prod.Product?.Name}");
|
||||
sb.Append("Sets: ");
|
||||
var setNames = prod.Sets.Any()
|
||||
? string.Join(", ", prod.Sets.Select(s => s.SetName))
|
||||
: "No Sets.";
|
||||
sb.Append(setNames);
|
||||
word.AddParagraph(sb.ToString());
|
||||
sb.Clear();
|
||||
}
|
||||
|
||||
// Генерируем и сохраняем
|
||||
using var stream = word.Build();
|
||||
// Убедимся, что позиция в потоке в начале
|
||||
if (stream.CanSeek) stream.Seek(0, SeekOrigin.Begin);
|
||||
File.WriteAllBytes(outputPath, ((MemoryStream)stream).ToArray());
|
||||
return word.Build();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Поддерживаются только форматы «doc» и «xls»", nameof(format));
|
||||
throw new ArgumentException("Only «doc» and «xls» formats are supported", nameof(format));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,8 +88,7 @@ namespace YAPBusinessLogic.Implementations
|
||||
/// </summary>
|
||||
/// <param name="productIds">Id товаров</param>
|
||||
/// <param name="format">doc/xls</param>
|
||||
/// <param name="outputPath">Пусть, куда сохранить файл</param>
|
||||
public void MakeReportProductSetsByProducts(List<string> productIds, string format, string outputPath)
|
||||
public Stream MakeReportProductSetsByProducts(List<string> productIds, string format)
|
||||
{
|
||||
// Получаем продукты по сборкам
|
||||
var productSets = _productSetStorageContract.GetListProductSetsByProducts(productIds);
|
||||
@@ -96,44 +96,45 @@ namespace YAPBusinessLogic.Implementations
|
||||
if (string.Equals(format, "xls", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var excel = new OpenXmlExcelBuilder();
|
||||
// Заголовок
|
||||
excel.AddHeader("Сборки - Изделия", 0, 4);
|
||||
// контент: Сборки и под ними изделия
|
||||
foreach (var prod in productSets)
|
||||
excel.AddHeader("Product Sets by Products", 0, 4);
|
||||
|
||||
var rows = new List<string[]>();
|
||||
rows.Add(new[] { "Product Set", "Products" });
|
||||
|
||||
foreach (var set in productSets)
|
||||
{
|
||||
excel.AddParagraph(prod.Set.SetName, 0);
|
||||
foreach (var wm in prod.Products)
|
||||
excel.AddParagraph($" {wm.Name}", 1);
|
||||
var productNames = set.Products.Any()
|
||||
? string.Join(", ", set.Products.Select(p => p.Name))
|
||||
: "Нет товаров";
|
||||
rows.Add(new[] { set.Set?.SetName ?? "-", productNames });
|
||||
}
|
||||
using var st = excel.Build();
|
||||
File.WriteAllBytes(outputPath, ((MemoryStream)st).ToArray());
|
||||
|
||||
excel.AddTable([10, 10], rows);
|
||||
return excel.Build();
|
||||
}
|
||||
else if (string.Equals(format, "doc", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var word = new OpenXmlWordBuilder();
|
||||
word.AddHeader("Product Sets by Products");
|
||||
|
||||
// Добавляем заголовок
|
||||
word.AddHeader("Изделия - Сборки");
|
||||
|
||||
// Добавляем контент: название изделия + список сборок
|
||||
foreach (var prod in productSets)
|
||||
foreach (var set in productSets)
|
||||
{
|
||||
word.AddParagraph(prod.Set.SetName);
|
||||
foreach (var wm in prod.Products)
|
||||
{
|
||||
word.AddParagraph($" {wm.Name}");
|
||||
}
|
||||
word.AddParagraph($"Сборка: {set.Set?.SetName}");
|
||||
sb.Append("Товары: ");
|
||||
var productNames = set.Products.Any()
|
||||
? string.Join(", ", set.Products.Select(p => p.Name))
|
||||
: "Нет товаров";
|
||||
sb.Append(productNames);
|
||||
word.AddParagraph(sb.ToString());
|
||||
sb.Clear();
|
||||
}
|
||||
|
||||
// Генерируем и сохраняем
|
||||
using var stream = word.Build();
|
||||
// Убедимся, что позиция в потоке в начале
|
||||
if (stream.CanSeek) stream.Seek(0, SeekOrigin.Begin);
|
||||
File.WriteAllBytes(outputPath, ((MemoryStream)stream).ToArray());
|
||||
return word.Build();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Поддерживаются только форматы «doc» и «xls»", nameof(format));
|
||||
throw new ArgumentException("Only «doc» and «xls» formats are supported", nameof(format));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,40 +145,40 @@ namespace YAPBusinessLogic.Implementations
|
||||
/// <param name="dateEnd">Конец периода</param>
|
||||
public Stream MakeReportByPurchases(DateTime dateStart, DateTime dateEnd)
|
||||
{
|
||||
_pdfBuilder.AddHeader("Отчет по продажам");
|
||||
_pdfBuilder.AddHeader("Purchases report");
|
||||
var reportData = _purchaseStorageContract.GetDataForReport(dateStart, dateEnd);
|
||||
_pdfBuilder.AddParagraph($"Период: {dateStart} — {dateEnd}");
|
||||
_pdfBuilder.AddParagraph($"Period: {dateStart.ToLocalTime()} — {dateEnd.ToLocalTime()}");
|
||||
|
||||
foreach (var sale in reportData)
|
||||
{
|
||||
_pdfBuilder.AddParagraph($"----------------------------------");
|
||||
_pdfBuilder.AddParagraph($"Дата продажи: {sale.Purchase.PurchaseDate}");
|
||||
_pdfBuilder.AddParagraph($"Сумма: {sale.Purchase.TotalPrice}");
|
||||
_pdfBuilder.AddParagraph($"Purchase date: {sale.Purchase.PurchaseDate}");
|
||||
_pdfBuilder.AddParagraph($"Total: {sale.Purchase.TotalPrice}");
|
||||
_pdfBuilder.AddParagraph($"");
|
||||
_pdfBuilder.AddParagraph($"Комплектующие");
|
||||
_pdfBuilder.AddParagraph($"Components");
|
||||
|
||||
if (sale.Components is { Count: > 0 })
|
||||
{
|
||||
_pdfBuilder.AddTable(
|
||||
new[] { "Название", "Тип" },
|
||||
new[] { "Name", "Type" },
|
||||
sale.Components.Select(p => new[] { p.Name, p.ComponentType.ToString() }).ToList()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pdfBuilder.AddParagraph("Комплектующих не найдено.");
|
||||
_pdfBuilder.AddParagraph("No components found.");
|
||||
}
|
||||
_pdfBuilder.AddParagraph($"Комментарии");
|
||||
_pdfBuilder.AddParagraph($"Comments");
|
||||
if (sale.Comments is { Count: > 0 })
|
||||
{
|
||||
_pdfBuilder.AddTable(
|
||||
new[] { "Текст", "Дата" },
|
||||
new[] { "Text", "Date" },
|
||||
sale.Comments.Select(p => new[] { p.Text, p.Date.ToString("dd.MM.yyyy") }).ToList()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pdfBuilder.AddParagraph("Комментариев не найдено.");
|
||||
_pdfBuilder.AddParagraph("No comments found.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,40 +193,44 @@ namespace YAPBusinessLogic.Implementations
|
||||
/// <param name="dateEnd">Конец периода</param>
|
||||
public Stream MakeReportByComponents(DateTime dateStart, DateTime dateEnd)
|
||||
{
|
||||
_pdfBuilder.AddHeader("Отчет по комплектующим");
|
||||
if (dateEnd < dateStart)
|
||||
{
|
||||
throw new ArgumentException("End date must be later than start date.");
|
||||
}
|
||||
_pdfBuilder.AddHeader("Components report");
|
||||
var reportData = _componentStorageContract.GetDataForReport(dateStart, dateEnd);
|
||||
_pdfBuilder.AddParagraph($"Период: {dateStart} — {dateEnd}");
|
||||
_pdfBuilder.AddParagraph($"Period: {dateStart.ToLocalTime()} — {dateEnd.ToLocalTime()}");
|
||||
|
||||
foreach (var comp in reportData)
|
||||
{
|
||||
_pdfBuilder.AddParagraph($"----------------------------------");
|
||||
_pdfBuilder.AddParagraph($"Имя: {comp.Component.Name}");
|
||||
_pdfBuilder.AddParagraph($"Тип: {comp.Component.ComponentType}");
|
||||
_pdfBuilder.AddParagraph($"Name: {comp.Component.Name}");
|
||||
_pdfBuilder.AddParagraph($"Type: {comp.Component.ComponentType}");
|
||||
_pdfBuilder.AddParagraph($"");
|
||||
_pdfBuilder.AddParagraph($"Покупки");
|
||||
_pdfBuilder.AddParagraph($"Purchases");
|
||||
|
||||
if (comp.Purchases is { Count: > 0 })
|
||||
{
|
||||
_pdfBuilder.AddTable(
|
||||
new[] { "Дата", "Сумма" },
|
||||
new[] { "Date", "Sum" },
|
||||
comp.Purchases.Select(p => new[] { p.PurchaseDate.ToString("MM/dd/yy"), p.TotalPrice.ToString() }).ToList()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pdfBuilder.AddParagraph("Покупок не найдено.");
|
||||
_pdfBuilder.AddParagraph("No purchases found.");
|
||||
}
|
||||
_pdfBuilder.AddParagraph($"Заказы");
|
||||
_pdfBuilder.AddParagraph($"Orders");
|
||||
if (comp.Orders is { Count: > 0 })
|
||||
{
|
||||
_pdfBuilder.AddTable(
|
||||
new[] { "Дата", "Имя" },
|
||||
new[] { "Date", "Dealer Name" },
|
||||
comp.Orders.Select(p => new[] { p.OrderDate.ToString("dd.MM.yyyy"), p.DealerName }).ToList()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pdfBuilder.AddParagraph("Заказов не найдено.");
|
||||
_pdfBuilder.AddParagraph("No orders found.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,5 +19,7 @@ namespace YAPContracts.BindingModels
|
||||
[Required(ErrorMessage = "This field is required")]
|
||||
[Display(Name = "Component Type")]
|
||||
public string? ComponentType { get; set; }
|
||||
|
||||
public List<string>? ProductSetIds { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace YAPContracts.BusinessLogicContracts
|
||||
{
|
||||
public interface IReportBusinessLogicContract
|
||||
{
|
||||
Stream MakeReportProductsByProductSets(List<string> setsIds, string format);
|
||||
Stream MakeReportProductSetsByProducts(List<string> productIds, string format);
|
||||
public Stream MakeReportByPurchases(DateTime dateStart, DateTime dateEnd);
|
||||
public Stream MakeReportByComponents(DateTime dateStart, DateTime dateEnd);
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,17 @@ public class ComponentDataModel : IValidation
|
||||
public string Name { get; private set; }
|
||||
public ComponentType ComponentType { get; private set; }
|
||||
public bool IsDeleted { get; private set; }
|
||||
|
||||
// public List<ComponentInProductDataModel> Products = products;
|
||||
// public List<ComponentInProductSetDataModel> ProductSets = productSets;
|
||||
|
||||
public ComponentDataModel(string id, string name, ComponentType componentType, bool isDeleted)
|
||||
// public List<ComponentInProductDataModel> Products = products;
|
||||
public List<ComponentInProductSetDataModel> ProductSets { get; private set; }
|
||||
|
||||
public ComponentDataModel(string id, string name, ComponentType componentType, bool isDeleted, List<ComponentInProductSetDataModel> productSets)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
ComponentType = componentType;
|
||||
IsDeleted = isDeleted;
|
||||
ProductSets = productSets;
|
||||
}
|
||||
|
||||
public ComponentDataModel()
|
||||
@@ -34,6 +35,7 @@ public class ComponentDataModel : IValidation
|
||||
Name = string.Empty;
|
||||
ComponentType = ComponentType.None;
|
||||
IsDeleted = false;
|
||||
ProductSets = new List<ComponentInProductSetDataModel>();
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
|
||||
@@ -18,4 +18,5 @@ public interface IComponentStorageContract
|
||||
void UpdElement(ComponentDataModel componentDataModel);
|
||||
|
||||
void DelElement(string id);
|
||||
List<ComponentReportModel>? GetDataForReport(DateTime start, DateTime finish);
|
||||
}
|
||||
|
||||
@@ -15,5 +15,6 @@ namespace YAPContracts.StorageContracts
|
||||
void AddElement(ProductSetDataModel productSet);
|
||||
void UpdateElement(ProductSetDataModel productSet);
|
||||
void DeleteElement(string id);
|
||||
List<SetWithProductsDataModel> GetListProductSetsByProducts(List<string> prodIds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,6 @@ public interface IProductStorageContract
|
||||
void UpdElement(ProductDataModel ProductDataModel);
|
||||
|
||||
void DelElement(string id);
|
||||
|
||||
List<ProductWithSetsDataModel> GetListProductsByProductSet(List<string> setsIds);
|
||||
}
|
||||
|
||||
@@ -14,5 +14,6 @@ namespace YAPContracts.StorageContracts
|
||||
void AddElement(PurchaseDataModel purchase);
|
||||
void UpdateElement(PurchaseDataModel purchase);
|
||||
void DeleteElement(string id);
|
||||
List<PurchasesReportModel>? GetDataForReport(DateTime start, DateTime finish);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,6 @@ public class ComponentViewModel
|
||||
public string Id { get; set; } = default!;
|
||||
public string Name { get; set; } = default!;
|
||||
public ComponentType ComponentType { get; set; }
|
||||
|
||||
public List<string>? ProductSetIds { get; set; }
|
||||
}
|
||||
@@ -42,7 +42,8 @@ internal class ComponentStorageContract : IComponentStorageContract
|
||||
{
|
||||
try
|
||||
{
|
||||
_dbContext.Components.Add(_mapper.Map<Component>(component));
|
||||
var entity = _mapper.Map<Component>(component);
|
||||
_dbContext.Components.Add(entity);
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -89,7 +90,7 @@ internal class ComponentStorageContract : IComponentStorageContract
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<ComponentDataModel>(_dbContext.Components.FirstOrDefault(x => x.Name == name));
|
||||
return _mapper.Map<ComponentDataModel>(_dbContext.Components.Include(x => x.ProductSets).FirstOrDefault(x => x.Name == name));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -132,7 +133,7 @@ internal class ComponentStorageContract : IComponentStorageContract
|
||||
}
|
||||
}
|
||||
|
||||
private Component? GetComponentById(string id) => _dbContext.Components.FirstOrDefault(x => x.Id == id);
|
||||
private Component? GetComponentById(string id) => _dbContext.Components.Include(x => x.ProductSets).FirstOrDefault(x => x.Id == id);
|
||||
|
||||
public List<ComponentReportModel>? GetDataForReport(DateTime start, DateTime finish)
|
||||
{
|
||||
@@ -143,11 +144,11 @@ internal class ComponentStorageContract : IComponentStorageContract
|
||||
{
|
||||
Component = _mapper.Map<ComponentDataModel>(c),
|
||||
Purchases = c.Products
|
||||
.SelectMany(cp => cp.Product.ProductsInPurchace)
|
||||
.SelectMany(cp => cp.Product.ProductsInPurchace).Where(pip => pip.Purchase.PurchaseDate >= start && pip.Purchase.PurchaseDate <= finish)
|
||||
.Select(pip => _mapper.Map<PurchaseDataModel>(pip.Purchase))
|
||||
.ToList(),
|
||||
Orders = c.Products
|
||||
.SelectMany(p => p.Product.ProductOrders)
|
||||
.SelectMany(p => p.Product.ProductOrders).Where(po => po.OrderDate >= start && po.OrderDate <= finish)
|
||||
.Select(ord => _mapper.Map<ProductOrderDataModel>(ord))
|
||||
.ToList()
|
||||
})
|
||||
|
||||
@@ -166,7 +166,7 @@ namespace YAPDatabase.Implementations
|
||||
{
|
||||
try
|
||||
{
|
||||
return _dbContext.ProductSets
|
||||
return _dbContext.ProductSets.Where(x => x.IsDeleted != true)
|
||||
.Where(p => p.ComponentsInProductSet
|
||||
.Any(cp => cp.Component.Products
|
||||
.Any(cps => prodIds.Contains(cps.ProductId))))
|
||||
|
||||
@@ -20,8 +20,25 @@ namespace YAPWebApplication.Adapters
|
||||
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.CreateMap<ComponentBindingModel, ComponentDataModel>();
|
||||
cfg.CreateMap<ComponentDataModel, ComponentViewModel>();
|
||||
cfg.CreateMap<ComponentBindingModel, ComponentDataModel>()
|
||||
.ForMember(dest => dest.ProductSets,
|
||||
opt => opt.MapFrom(src =>
|
||||
(src.ProductSetIds ?? new List<string>())
|
||||
.Select(psId => new ComponentInProductSetDataModel(
|
||||
src.Id ?? Guid.NewGuid().ToString(),
|
||||
psId,
|
||||
1
|
||||
)).ToList()
|
||||
)
|
||||
);
|
||||
|
||||
cfg.CreateMap<ComponentDataModel, ComponentViewModel>()
|
||||
.ForMember(dest => dest.ProductSetIds,
|
||||
opt => opt.MapFrom(src =>
|
||||
src.ProductSets.Select(ps => ps.ProductSetId).ToList()
|
||||
)
|
||||
);
|
||||
|
||||
cfg.CreateMap<ComponentViewModel, ComponentDataModel>();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class CommentController : Controller
|
||||
{
|
||||
private readonly ICommentAdapter _commentAdapter;
|
||||
|
||||
public CommentController(ICommentAdapter commentAdapter)
|
||||
{
|
||||
_commentAdapter = commentAdapter;
|
||||
}
|
||||
|
||||
// GET: /Comment/
|
||||
public IActionResult Index()
|
||||
{
|
||||
var comments = _commentAdapter.GetList();
|
||||
return View(comments);
|
||||
}
|
||||
|
||||
// GET: /Comment/Details/{id}
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var comment = _commentAdapter.GetCommentById(id);
|
||||
if (comment == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(comment);
|
||||
}
|
||||
|
||||
// GET: /Comment/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: /Comment/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(CommentBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_commentAdapter.Create(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Comment/Edit/{id}
|
||||
public IActionResult Edit(string id)
|
||||
{
|
||||
var comment = _commentAdapter.GetCommentById(id);
|
||||
if (comment == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(comment);
|
||||
}
|
||||
|
||||
// POST: /Comment/Edit
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Edit(CommentBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_commentAdapter.Update(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Comment/Delete/{id}
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
var comment = _commentAdapter.GetCommentById(id);
|
||||
if (comment == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(comment);
|
||||
}
|
||||
|
||||
// POST: /Comment/Delete
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult DeleteConfirmed(string id)
|
||||
{
|
||||
_commentAdapter.Delete(id);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class ComponentController : Controller
|
||||
{
|
||||
private readonly IComponentAdapter _componentAdapter;
|
||||
|
||||
public ComponentController(IComponentAdapter componentAdapter)
|
||||
{
|
||||
_componentAdapter = componentAdapter;
|
||||
}
|
||||
|
||||
// GET: /Component/
|
||||
public IActionResult Index()
|
||||
{
|
||||
var sets = _componentAdapter.GetList(true);
|
||||
return View(sets);
|
||||
}
|
||||
|
||||
// GET: /Component/Details/{id}
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var set = _componentAdapter.GetComponentByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// GET: /Component/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: /Component/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(ComponentBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_componentAdapter.Insert(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Component/Edit/{id}
|
||||
public IActionResult Edit(string id)
|
||||
{
|
||||
var set = _componentAdapter.GetComponentByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// POST: /Component/Edit
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Edit(ComponentBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_componentAdapter.Update(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Component/Delete/{id}
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
var set = _componentAdapter.GetComponentByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// POST: /Component/Delete
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult DeleteConfirmed(string id)
|
||||
{
|
||||
_componentAdapter.Delete(id);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class ProductController : Controller
|
||||
{
|
||||
private readonly IProductAdapter _productAdapter;
|
||||
|
||||
public ProductController(IProductAdapter productAdapter)
|
||||
{
|
||||
_productAdapter = productAdapter;
|
||||
}
|
||||
|
||||
// GET: /Product/
|
||||
public IActionResult Index()
|
||||
{
|
||||
var sets = _productAdapter.GetList();
|
||||
return View(sets);
|
||||
}
|
||||
|
||||
// GET: /Product/Details/{id}
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var set = _productAdapter.GetProductByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// GET: /Product/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: /Product/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(ProductBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_productAdapter.Insert(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Product/Edit/{id}
|
||||
public IActionResult Edit(string id)
|
||||
{
|
||||
var set = _productAdapter.GetProductByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// POST: /Product/Edit
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Edit(ProductBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_productAdapter.Update(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Product/Delete/{id}
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
var set = _productAdapter.GetProductByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// POST: /Product/Delete
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult DeleteConfirmed(string id)
|
||||
{
|
||||
_productAdapter.Delete(id);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class ProductOrderController : Controller
|
||||
{
|
||||
private readonly IProductOrderAdapter _adapter;
|
||||
|
||||
public ProductOrderController(IProductOrderAdapter adapter)
|
||||
{
|
||||
_adapter = adapter;
|
||||
}
|
||||
|
||||
// список всех заказов
|
||||
public IActionResult Index()
|
||||
{
|
||||
var orders = _adapter.GetList();
|
||||
return View(orders);
|
||||
}
|
||||
|
||||
// просмотр деталей
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var order = _adapter.GetElement(id);
|
||||
if (order == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(order);
|
||||
}
|
||||
|
||||
// форма создания
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(ProductOrderBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_adapter.RegisterProductOrder(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// заказы за период
|
||||
public IActionResult ByPeriod(DateTime fromDate, DateTime toDate)
|
||||
{
|
||||
var orders = _adapter.GetListByPeriod(fromDate, toDate);
|
||||
return View("Index", orders); // можно отдельное представление
|
||||
}
|
||||
|
||||
// заказы по продукту за период
|
||||
public IActionResult ByProductAndPeriod(string productId, DateTime fromDate, DateTime toDate)
|
||||
{
|
||||
var orders = _adapter.GetListByProductAndPeriod(productId, fromDate, toDate);
|
||||
return View("Index", orders);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class ProductSetController : Controller
|
||||
{
|
||||
private readonly IProductSetAdapter _productSetAdapter;
|
||||
|
||||
public ProductSetController(IProductSetAdapter productSetAdapter)
|
||||
{
|
||||
_productSetAdapter = productSetAdapter;
|
||||
}
|
||||
|
||||
// GET: /ProductSet/
|
||||
public IActionResult Index()
|
||||
{
|
||||
var sets = _productSetAdapter.GetList();
|
||||
return View(sets);
|
||||
}
|
||||
|
||||
// GET: /ProductSet/Details/{id}
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var set = _productSetAdapter.GetProductSetByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// GET: /ProductSet/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: /ProductSet/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(ProductSetBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_productSetAdapter.Insert(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /ProductSet/Edit/{id}
|
||||
public IActionResult Edit(string id)
|
||||
{
|
||||
var set = _productSetAdapter.GetProductSetByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// POST: /ProductSet/Edit
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Edit(ProductSetBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_productSetAdapter.Update(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /ProductSet/Delete/{id}
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
var set = _productSetAdapter.GetProductSetByData(id);
|
||||
if (set == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(set);
|
||||
}
|
||||
|
||||
// POST: /ProductSet/Delete
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult DeleteConfirmed(string id)
|
||||
{
|
||||
_productSetAdapter.Delete(id);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
using YAPContracts.BusinessLogicContracts;
|
||||
using YAPContracts.DataModels;
|
||||
using YAPContracts.ViewModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class PurchaseController : Controller
|
||||
{
|
||||
private readonly IPurchaseAdapter _purchaseAdapter;
|
||||
|
||||
public PurchaseController(IPurchaseAdapter purchaseAdapter)
|
||||
{
|
||||
_purchaseAdapter = purchaseAdapter;
|
||||
}
|
||||
|
||||
// список всех покупок
|
||||
public IActionResult Index()
|
||||
{
|
||||
var purchases = _purchaseAdapter.GetList();
|
||||
return View(purchases);
|
||||
}
|
||||
|
||||
// просмотр деталей
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var purchase = _purchaseAdapter.GetElement(id);
|
||||
if (purchase == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(purchase);
|
||||
}
|
||||
|
||||
// форма добавления
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(PurchaseBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_purchaseAdapter.Register(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// форма редактирования
|
||||
public IActionResult Edit(string id)
|
||||
{
|
||||
var purchase = _purchaseAdapter.GetElement(id);
|
||||
if (purchase == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var bindingModel = new PurchaseBindingModel
|
||||
{
|
||||
Id = purchase.Id,
|
||||
UserId = purchase.UserId,
|
||||
PurchaseDate = purchase.PurchaseDate,
|
||||
TotalPrice = purchase.TotalPrice,
|
||||
// сюда можно маппить связанные продукты/сборки
|
||||
};
|
||||
|
||||
return View(bindingModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Edit(PurchaseBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_purchaseAdapter.Update(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// удаление
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
var purchase = _purchaseAdapter.GetElement(id);
|
||||
if (purchase == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(purchase);
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult DeleteConfirmed(string id)
|
||||
{
|
||||
_purchaseAdapter.Delete(id);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class StorekeeperController : Controller
|
||||
{
|
||||
private readonly IStorekeeperAdapter _storekeeperAdapter;
|
||||
|
||||
public StorekeeperController(IStorekeeperAdapter storekeeperAdapter)
|
||||
{
|
||||
_storekeeperAdapter = storekeeperAdapter;
|
||||
}
|
||||
|
||||
// список всех работников
|
||||
public IActionResult Index()
|
||||
{
|
||||
var storekeepers = _storekeeperAdapter.GetList();
|
||||
return View(storekeepers);
|
||||
}
|
||||
|
||||
// просмотр деталей конкретного работника
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var storekeeper = _storekeeperAdapter.GetElement(id);
|
||||
if (storekeeper == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(storekeeper);
|
||||
}
|
||||
|
||||
// GET: форма создания
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: создание нового работника
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(StorekeeperBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_storekeeperAdapter.Register(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: форма редактирования
|
||||
public IActionResult Edit(string id)
|
||||
{
|
||||
var storekeeper = _storekeeperAdapter.GetElement(id);
|
||||
if (storekeeper == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
// для редактирования можно заполнить BindingModel из ViewModel
|
||||
var bindingModel = new StorekeeperBindingModel
|
||||
{
|
||||
Id = storekeeper.Id,
|
||||
Login = storekeeper.Login,
|
||||
Email = storekeeper.Email,
|
||||
Password = "", // пароль редактируется отдельно
|
||||
};
|
||||
|
||||
return View(bindingModel);
|
||||
}
|
||||
|
||||
// POST: обновление данных
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Edit(StorekeeperBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_storekeeperAdapter.Update(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: форма удаления
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
var storekeeper = _storekeeperAdapter.GetElement(id);
|
||||
if (storekeeper == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(storekeeper);
|
||||
}
|
||||
|
||||
// POST: подтверждение удаления
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult DeleteConfirmed(string id)
|
||||
{
|
||||
_storekeeperAdapter.Delete(id);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
|
||||
namespace YAPWebApplication.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class WorkerController : Controller
|
||||
{
|
||||
private readonly IWorkerAdapter _workerAdapter;
|
||||
|
||||
public WorkerController(IWorkerAdapter workerAdapter)
|
||||
{
|
||||
_workerAdapter = workerAdapter;
|
||||
}
|
||||
|
||||
// список всех работников
|
||||
public IActionResult Index()
|
||||
{
|
||||
var workers = _workerAdapter.GetList();
|
||||
return View(workers);
|
||||
}
|
||||
|
||||
// просмотр деталей конкретного работника
|
||||
public IActionResult Details(string id)
|
||||
{
|
||||
var worker = _workerAdapter.GetElement(id);
|
||||
if (worker == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(worker);
|
||||
}
|
||||
|
||||
// GET: форма создания
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: создание нового работника
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Create(WorkerBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_workerAdapter.Register(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: форма редактирования
|
||||
public IActionResult Edit(string id)
|
||||
{
|
||||
var worker = _workerAdapter.GetElement(id);
|
||||
if (worker == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
// для редактирования можно заполнить BindingModel из ViewModel
|
||||
var bindingModel = new WorkerBindingModel
|
||||
{
|
||||
Id = worker.Id,
|
||||
Login = worker.Login,
|
||||
Email = worker.Email,
|
||||
Password = "", // пароль редактируется отдельно
|
||||
};
|
||||
|
||||
return View(bindingModel);
|
||||
}
|
||||
|
||||
// POST: обновление данных
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Edit(WorkerBindingModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_workerAdapter.Update(model);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: форма удаления
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
var worker = _workerAdapter.GetElement(id);
|
||||
if (worker == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(worker);
|
||||
}
|
||||
|
||||
// POST: подтверждение удаления
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult DeleteConfirmed(string id)
|
||||
{
|
||||
_workerAdapter.Delete(id);
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using MailKit.Net.Smtp;
|
||||
using MimeKit;
|
||||
|
||||
namespace YAPWebApplication.Infrastructure
|
||||
{
|
||||
public interface IEmailService
|
||||
{
|
||||
Task SendEmailAsync(string to, string subject, string body, Stream? attachment = null, string? fileName = null);
|
||||
}
|
||||
|
||||
public class EmailService : IEmailService
|
||||
{
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
public EmailService(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public async Task SendEmailAsync(string to, string subject, string body, Stream? attachment = null, string? fileName = null)
|
||||
{
|
||||
var emailMessage = new MimeMessage();
|
||||
emailMessage.From.Add(new MailboxAddress("Shop Reports", _config["Email:SmtpUser"]));
|
||||
emailMessage.To.Add(MailboxAddress.Parse(to));
|
||||
emailMessage.Subject = subject;
|
||||
|
||||
var builder = new BodyBuilder { HtmlBody = body };
|
||||
|
||||
if (attachment != null && fileName != null)
|
||||
{
|
||||
attachment.Seek(0, SeekOrigin.Begin);
|
||||
builder.Attachments.Add(fileName, attachment);
|
||||
}
|
||||
|
||||
emailMessage.Body = builder.ToMessageBody();
|
||||
|
||||
using var client = new SmtpClient();
|
||||
await client.ConnectAsync(_config["Email:SmtpServer"], int.Parse(_config["Email:SmtpPort"]), true);
|
||||
await client.AuthenticateAsync(_config["Email:SmtpUser"], _config["Email:SmtpPass"]);
|
||||
try
|
||||
{
|
||||
await client.SendAsync(emailMessage);
|
||||
await client.DisconnectAsync(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the exception or handle it as needed
|
||||
throw new InvalidOperationException(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,18 @@
|
||||
</div>
|
||||
|
||||
<div class="list-group">
|
||||
<a asp-page="/Views/Comments/Index" class="list-group-item list-group-item-action">Comments</a>
|
||||
<a asp-page="/Views/Components/Index" class="list-group-item list-group-item-action">Components</a>
|
||||
<a asp-page="/Views/Products/Index" class="list-group-item list-group-item-action">Products</a>
|
||||
<a asp-page="/Views/ProductSets/Index" class="list-group-item list-group-item-action">Product Sets</a>
|
||||
<a asp-page="/Views/ProductOrders/Index" class="list-group-item list-group-item-action">Product Orders</a>
|
||||
<a asp-page="/Views/Purchases/Index" class="list-group-item list-group-item-action">Purchases</a>
|
||||
<a asp-page="/Reports/Index" class="list-group-item list-group-item-action">Reports</a>
|
||||
@if (User.IsInRole("Worker")){
|
||||
<a asp-page="/Views/Comments/Index" class="list-group-item list-group-item-action">Comments</a>
|
||||
<a asp-page="/Views/ProductSets/Index" class="list-group-item list-group-item-action">Product Sets</a>
|
||||
<a asp-page="/Views/Purchases/Index" class="list-group-item list-group-item-action">Purchases</a>
|
||||
}
|
||||
@if (User.IsInRole("Storekeeper"))
|
||||
{
|
||||
<a asp-page="/Views/Components/Index" class="list-group-item list-group-item-action">Components</a>
|
||||
<a asp-page="/Views/Products/Index" class="list-group-item list-group-item-action">Products</a>
|
||||
<a asp-page="/Views/ProductOrders/Index" class="list-group-item list-group-item-action">Product Orders</a>
|
||||
}
|
||||
|
||||
|
||||
<a asp-page="/Views/Reports/Index" class="list-group-item list-group-item-action">Reports</a>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@model YAPWebApplication.Pages.Views.Comments.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
ViewData["Title"] = "Comments";
|
||||
}
|
||||
|
||||
<h1>Comments</h1>
|
||||
|
||||
@@ -24,6 +24,20 @@
|
||||
asp-items="Model.ComponentTypeList"></select>
|
||||
<span asp-validation-for="Component.ComponentType" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ProductSets">Add to Product Set</label>
|
||||
@foreach (var set in Model.ProductSetsList)
|
||||
{
|
||||
<div class="form-check">
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
name="Component.ProductSetIds"
|
||||
value="@set.Value"
|
||||
@(set.Selected ? "checked" : "") />
|
||||
<label class="form-check-label">@set.Text</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Create" class="btn btn-primary" />
|
||||
</div>
|
||||
|
||||
@@ -18,20 +18,23 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
public class CreateModel : PageModel
|
||||
{
|
||||
private readonly IComponentAdapter _componentAdapter;
|
||||
private readonly IProductSetAdapter _productSetAdapter;
|
||||
|
||||
public CreateModel(IComponentAdapter componentAdapter)
|
||||
public CreateModel(IComponentAdapter componentAdapter, IProductSetAdapter productSetAdapter)
|
||||
{
|
||||
_componentAdapter = componentAdapter;
|
||||
_productSetAdapter = productSetAdapter;
|
||||
}
|
||||
|
||||
public IEnumerable<SelectListItem>? ComponentTypeList { get; set; }
|
||||
public IEnumerable<SelectListItem>? ProductSetsList { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public ComponentBindingModel Component { get; set; } = new();
|
||||
|
||||
public IActionResult OnGet()
|
||||
{
|
||||
LoadComponentTypeList();
|
||||
LoadLists();
|
||||
return Page();
|
||||
}
|
||||
|
||||
@@ -39,7 +42,7 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
LoadComponentTypeList();
|
||||
LoadLists();
|
||||
return Page();
|
||||
}
|
||||
|
||||
@@ -52,12 +55,12 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, $"Ошибка: {ex.Message}");
|
||||
LoadComponentTypeList();
|
||||
LoadLists();
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadComponentTypeList()
|
||||
private void LoadLists()
|
||||
{
|
||||
ComponentTypeList = Enum.GetValues(typeof(ComponentType))
|
||||
.Cast<ComponentType>()
|
||||
@@ -66,6 +69,12 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
Value = ((int)ct).ToString(),
|
||||
Text = ct.ToString()
|
||||
});
|
||||
var prodSets = _productSetAdapter.GetList();
|
||||
ProductSetsList = prodSets?.Select(c => new SelectListItem
|
||||
{
|
||||
Value = c.Id,
|
||||
Text = $"{c.SetName}"
|
||||
}).ToList() ?? new List<SelectListItem>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,24 @@
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Component.ComponentType)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
Product Sets
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@if (Model.ProductSets != null && Model.ProductSets.Any())
|
||||
{
|
||||
<ul>
|
||||
@foreach (var comp in Model.ProductSets)
|
||||
{
|
||||
<li>@comp.SetName</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Does not appear in Product Sets</span>
|
||||
}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -14,25 +14,36 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
{
|
||||
internal class DetailsModel : PageModel
|
||||
{
|
||||
private readonly IComponentAdapter _adapter;
|
||||
private readonly IComponentAdapter _componentAdapter;
|
||||
private readonly IProductSetAdapter _productSetAdapter;
|
||||
|
||||
public DetailsModel(IComponentAdapter adapter)
|
||||
public DetailsModel(IComponentAdapter adapter, IProductSetAdapter productSetAdapter)
|
||||
{
|
||||
_adapter = adapter;
|
||||
_componentAdapter = adapter;
|
||||
_productSetAdapter = productSetAdapter;
|
||||
}
|
||||
|
||||
public ComponentViewModel? Component { get; set; }
|
||||
public List<ProductSetViewModel>? ProductSets { get; set; }
|
||||
|
||||
public IActionResult OnGet(string id)
|
||||
{
|
||||
if (id == null)
|
||||
return NotFound();
|
||||
|
||||
Component = _adapter.GetComponentByData(id);
|
||||
Component = _componentAdapter.GetComponentByData(id);
|
||||
|
||||
if (Component == null)
|
||||
return NotFound();
|
||||
|
||||
var allSets = _productSetAdapter.GetList();
|
||||
if (allSets != null && Component.ProductSetIds.Any())
|
||||
{
|
||||
ProductSets = allSets
|
||||
.Where(c => Component.ProductSetIds.Contains(c.Id))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,20 @@
|
||||
asp-items="Model.ComponentTypeList"></select>
|
||||
<span asp-validation-for="Component.ComponentType" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Product Sets</label>
|
||||
@foreach (var comp in Model.ProductSetSelectList)
|
||||
{
|
||||
<div class="form-check">
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
name="Component.ProductSetIds"
|
||||
value="@comp.Value"
|
||||
@(comp.Selected ? "checked" : "") />
|
||||
<label class="form-check-label">@comp.Text</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Save" class="btn btn-primary" />
|
||||
</div>
|
||||
|
||||
@@ -1,30 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
using YAPContracts.Enums;
|
||||
using YAPDatabase;
|
||||
using YAPDatabase.Models;
|
||||
using YAPWebApplication.Adapters;
|
||||
|
||||
namespace YAPWebApplication.Pages.Views.Components
|
||||
{
|
||||
[Authorize(Roles = "Storekeeper")]
|
||||
internal class EditModel : PageModel
|
||||
{
|
||||
private readonly IComponentAdapter _adapter;
|
||||
private readonly IComponentAdapter _componentAdapter;
|
||||
private readonly IProductSetAdapter _productSetAdapter;
|
||||
|
||||
public EditModel(IComponentAdapter adapter)
|
||||
public EditModel(IComponentAdapter adapter, IProductSetAdapter productSetAdapter)
|
||||
{
|
||||
_adapter = adapter;
|
||||
_componentAdapter = adapter;
|
||||
_productSetAdapter = productSetAdapter;
|
||||
}
|
||||
public IEnumerable<SelectListItem>? ComponentTypeList { get; set; }
|
||||
public List<SelectListItem> ProductSetSelectList { get; set; } = new();
|
||||
|
||||
|
||||
[BindProperty]
|
||||
@@ -35,7 +39,7 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
if (id == null)
|
||||
return NotFound();
|
||||
|
||||
var component = _adapter.GetComponentByData(id);
|
||||
var component = _componentAdapter.GetComponentByData(id);
|
||||
if (component == null)
|
||||
return NotFound();
|
||||
LoadComponentTypeList();
|
||||
@@ -45,7 +49,15 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
Id = component.Id,
|
||||
Name = component.Name,
|
||||
ComponentType = component.ComponentType.ToString(),
|
||||
ProductSetIds = component.ProductSetIds,
|
||||
};
|
||||
var prodSets = _productSetAdapter.GetList();
|
||||
ProductSetSelectList = prodSets?.Select(c => new SelectListItem
|
||||
{
|
||||
Value = c.Id,
|
||||
Text = $"{c.SetName}",
|
||||
Selected = Component.ProductSetIds.Contains(c.Id)
|
||||
}).ToList() ?? new List<SelectListItem>();
|
||||
|
||||
return Page();
|
||||
}
|
||||
@@ -55,17 +67,19 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
LoadComponentTypeList();
|
||||
LoadSetsList();
|
||||
return Page();
|
||||
}
|
||||
try
|
||||
{
|
||||
_adapter.Update(Component);
|
||||
_componentAdapter.Update(Component);
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, $"Ошибка: {ex.Message}");
|
||||
LoadComponentTypeList();
|
||||
LoadSetsList();
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
@@ -80,6 +94,21 @@ namespace YAPWebApplication.Pages.Views.Components
|
||||
Text = ct.ToString()
|
||||
});
|
||||
}
|
||||
private void LoadSetsList()
|
||||
{
|
||||
var prodSets = _productSetAdapter.GetList();
|
||||
if (Component.ProductSetIds == null)
|
||||
{
|
||||
ProductSetSelectList = new List<SelectListItem>();
|
||||
return;
|
||||
}
|
||||
ProductSetSelectList = prodSets?.Select(c => new SelectListItem
|
||||
{
|
||||
Value = c.Id,
|
||||
Text = $"{c.SetName}",
|
||||
Selected = Component.ProductSetIds.Contains(c.Id)
|
||||
}).ToList() ?? new List<SelectListItem>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
@model YAPWebApplication.Pages.Views.Components.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
ViewData["Title"] = "Components";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
<h1>Components</h1>
|
||||
@if (User.IsInRole("Storekeeper"))
|
||||
{
|
||||
<p>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
@model YAPWebApplication.Pages.Views.ProductOrders.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
ViewData["Title"] = "Product Orders";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
<h1>Product Orders</h1>
|
||||
@if (User.IsInRole("Storekeeper"))
|
||||
{
|
||||
<p>
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace YAPWebApplication.Pages.Views.ProductSets
|
||||
SetName = productset.SetName,
|
||||
TotalPrice = productset.TotalPrice,
|
||||
ComponentIds = productset.ComponentIds?.ToList() ?? new List<string>(),
|
||||
// COMMENTS!!!
|
||||
};
|
||||
// список для чекбоксов
|
||||
var components = _componentAdapter.GetList(true);
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
@model YAPWebApplication.Pages.Views.ProductSets.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
ViewData["Title"] = "Product Sets";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
<h1>Product Sets</h1>
|
||||
@if (User.IsInRole("Worker"))
|
||||
{
|
||||
<p>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
@model YAPWebApplication.Pages.Views.Products.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
ViewData["Title"] = "Products";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
<h1>Products</h1>
|
||||
@if (User.IsInRole("Storekeeper"))
|
||||
{
|
||||
<p>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
@model YAPWebApplication.Pages.Views.Purchases.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
ViewData["Title"] = "Purchases";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
<h1>Purchases</h1>
|
||||
|
||||
@if (User.IsInRole("Worker"))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
@page
|
||||
@model YAPWebApplication.Pages.Views.Reports.ComponentsReportModel
|
||||
@{
|
||||
ViewData["Title"] = "Report: Components by date";
|
||||
}
|
||||
|
||||
<h1>Components report</h1>
|
||||
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>Start date</label>
|
||||
<input asp-for="DateStart" type="date" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>End date</label>
|
||||
<input asp-for="DateEnd" type="date" class="form-control" />
|
||||
</div>
|
||||
<div class="text-danger">
|
||||
@Html.ValidationSummary(false)
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Show report</button>
|
||||
</form>
|
||||
|
||||
@if (Model.ReportUrl != null)
|
||||
{
|
||||
<hr />
|
||||
<h3>PDF preview</h3>
|
||||
<iframe src="@Model.ReportUrl" width="100%" height="600px"></iframe>
|
||||
|
||||
<p class="mt-2">
|
||||
<a href="@Model.ReportUrl" class="btn btn-success" download>Download PDF</a>
|
||||
</p>
|
||||
}
|
||||
|
||||
<form method="post" asp-page-handler="SendEmail">
|
||||
<input type="hidden" asp-for="DateStart" />
|
||||
<input type="hidden" asp-for="DateEnd" />
|
||||
<div class="form-group">
|
||||
<label>Email</label>
|
||||
<input asp-for="RecipientEmail" type="email" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group mt-2">
|
||||
<button type="submit" class="btn btn-success">Send to Email</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if (TempData["Message"] != null)
|
||||
{
|
||||
<div class="alert alert-success mt-2">@TempData["Message"]</div>
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using DocumentFormat.OpenXml.Bibliography;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using System.Security.Claims;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BusinessLogicContracts;
|
||||
using YAPWebApplication.Infrastructure;
|
||||
|
||||
namespace YAPWebApplication.Pages.Views.Reports
|
||||
{
|
||||
internal class ComponentsReportModel : PageModel
|
||||
{
|
||||
private readonly IReportBusinessLogicContract _reportBL;
|
||||
private readonly IEmailService _emailService;
|
||||
private readonly IStorekeeperAdapter _storekeeperAdapter;
|
||||
|
||||
public ComponentsReportModel(
|
||||
IReportBusinessLogicContract reportBL,
|
||||
IEmailService emailService,
|
||||
IStorekeeperAdapter storekeeperAdapter)
|
||||
{
|
||||
_reportBL = reportBL;
|
||||
_emailService = emailService;
|
||||
_storekeeperAdapter = storekeeperAdapter;
|
||||
}
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public DateTime DateStart { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public DateTime DateEnd { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string RecipientEmail { get; set; } = string.Empty;
|
||||
|
||||
public string? ReportUrl { get; set; }
|
||||
|
||||
public IActionResult OnGet(string? reportFile = null)
|
||||
{
|
||||
if (DateStart == default)
|
||||
DateStart = DateTime.UtcNow.ToLocalTime();
|
||||
|
||||
if (DateEnd == default)
|
||||
DateEnd = DateTime.UtcNow.ToLocalTime().AddDays(7);
|
||||
|
||||
FillEmail();
|
||||
|
||||
if (!string.IsNullOrEmpty(reportFile))
|
||||
{
|
||||
ReportUrl = $"/reports/{reportFile}";
|
||||
}
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
public IActionResult OnPost()
|
||||
{
|
||||
FillEmail();
|
||||
|
||||
if (DateStart > DateEnd)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "End date must be later than start date!");
|
||||
return Page();
|
||||
}
|
||||
|
||||
var stream = _reportBL.MakeReportByComponents(DateStart.ToUniversalTime(), DateEnd.ToUniversalTime());
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var fileName = $"components_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf";
|
||||
var folderPath = Path.Combine("wwwroot", "reports");
|
||||
Directory.CreateDirectory(folderPath);
|
||||
|
||||
foreach (var file in Directory.GetFiles(folderPath, "*.pdf"))
|
||||
{
|
||||
var creationTime = System.IO.File.GetCreationTime(file);
|
||||
if (creationTime < DateTime.Now.AddDays(-1))
|
||||
{
|
||||
try { System.IO.File.Delete(file); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
var filePath = Path.Combine(folderPath, fileName);
|
||||
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
|
||||
return RedirectToPage(new
|
||||
{
|
||||
DateStart = DateStart.ToString("yyyy-MM-dd"),
|
||||
DateEnd = DateEnd.ToString("yyyy-MM-dd"),
|
||||
reportFile = fileName
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostSendEmail()
|
||||
{
|
||||
if (DateStart >= DateEnd)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "End date must be later than start date!");
|
||||
FillEmail();
|
||||
return Page();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(RecipientEmail))
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Email is required to send report!");
|
||||
FillEmail();
|
||||
return Page();
|
||||
}
|
||||
|
||||
var stream = _reportBL.MakeReportByComponents(DateStart.ToUniversalTime(), DateEnd.ToUniversalTime());
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
try
|
||||
{
|
||||
await _emailService.SendEmailAsync(
|
||||
RecipientEmail,
|
||||
"Components report",
|
||||
$"Components report for period {DateStart:dd.MM.yyyy} - {DateEnd:dd.MM.yyyy}",
|
||||
stream,
|
||||
$"components_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf"
|
||||
);
|
||||
|
||||
TempData["Message"] = "Report sent to Email!";
|
||||
|
||||
return RedirectToPage(new
|
||||
{
|
||||
DateStart = DateStart.ToString("yyyy-MM-dd"),
|
||||
DateEnd = DateEnd.ToString("yyyy-MM-dd"),
|
||||
reportFile = $"components_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, $"Failed to send email: {ex.Message}");
|
||||
FillEmail();
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
|
||||
private void FillEmail()
|
||||
{
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var user = _storekeeperAdapter.GetElement(userId);
|
||||
if (!string.IsNullOrWhiteSpace(user?.Email))
|
||||
RecipientEmail = user.Email;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
@page
|
||||
@model YAPWebApplication.Pages.Views.Reports.IndexModel
|
||||
@{
|
||||
ViewData["Title"] = "Reports";
|
||||
}
|
||||
|
||||
<h1>Get a report</h1>
|
||||
@if (User.IsInRole("Worker")) {
|
||||
<p>
|
||||
<a asp-page="ProductsByProductSetsReport" class="btn btn-primary">Products by ProductSets</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-page="PurchasesReport" class="btn btn-outline-dark">Purchases by date</a>
|
||||
</p>
|
||||
}
|
||||
@if (User.IsInRole("Storekeeper"))
|
||||
{
|
||||
<p>
|
||||
<a asp-page="ProductSetsByProductsReport" class="btn btn-primary">Product Sets by Products</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a asp-page="ComponentsReport" class="btn btn-outline-dark">Components by date</a>
|
||||
</p>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace YAPWebApplication.Pages.Views.Reports
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
public void OnGet()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
@page
|
||||
@model YAPWebApplication.Pages.Views.Reports.ProductSetsByProductsReportModel
|
||||
@{
|
||||
ViewData["Title"] = "Report: Sets by Products";
|
||||
}
|
||||
|
||||
<h1>Report: sets by products</h1>
|
||||
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>Choose a product</label>
|
||||
@foreach (var prod in Model.Products)
|
||||
{
|
||||
<div class="form-check">
|
||||
<input type="checkbox"
|
||||
name="SelectedProductIds"
|
||||
value="@prod.Value"
|
||||
class="form-check-input"
|
||||
id="prod_@prod.Value" />
|
||||
<label class="form-check-label" for="prod_@prod.Value">@prod.Text</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<div class="form-group">
|
||||
<label>Format</label>
|
||||
<select asp-for="Format" class="form-control">
|
||||
<option value="doc">Word (.docx)</option>
|
||||
<option value="xls">Excel (.xlsx)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Download</button>
|
||||
<a asp-page="./Index" class="btn btn-secondary">Back to List</a>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,55 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BusinessLogicContracts;
|
||||
|
||||
namespace YAPWebApplication.Pages.Views.Reports
|
||||
{
|
||||
internal class ProductSetsByProductsReportModel : PageModel
|
||||
{
|
||||
private readonly IReportBusinessLogicContract _reportBL;
|
||||
private readonly IProductAdapter _productAdapter;
|
||||
|
||||
public ProductSetsByProductsReportModel(IReportBusinessLogicContract reportBL, IProductAdapter productAdapter)
|
||||
{
|
||||
_reportBL = reportBL;
|
||||
_productAdapter = productAdapter;
|
||||
}
|
||||
|
||||
public List<SelectListItem> Products { get; set; } = new();
|
||||
|
||||
[BindProperty]
|
||||
public List<string> SelectedProductIds { get; set; } = new();
|
||||
|
||||
[BindProperty]
|
||||
public string Format { get; set; } = "doc";
|
||||
|
||||
public IActionResult OnGet()
|
||||
{
|
||||
LoadFormFields();
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
public IActionResult OnPost()
|
||||
{
|
||||
var stream = _reportBL.MakeReportProductSetsByProducts(SelectedProductIds, Format);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var fileName = $"sets_by_products.{Format}";
|
||||
var contentType = Format == "xls"
|
||||
? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
: "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
|
||||
return File(stream, contentType, fileName);
|
||||
}
|
||||
|
||||
private void LoadFormFields()
|
||||
{
|
||||
Products = _productAdapter.GetList()?
|
||||
.Select(p => new SelectListItem { Value = p.Id, Text = p.Name })
|
||||
.ToList() ?? new();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
@page
|
||||
@model YAPWebApplication.Pages.Views.Reports.ProductsByProductSetsReportModel
|
||||
@{
|
||||
ViewData["Title"] = "Report: Products by Sets";
|
||||
}
|
||||
|
||||
<h1>Products By Product Sets Report</h1>
|
||||
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Product Sets</label>
|
||||
@foreach (var set in Model.ProductSets)
|
||||
{
|
||||
<div class="form-check">
|
||||
<input type="checkbox"
|
||||
name="SelectedProductSetIds"
|
||||
value="@set.Value"
|
||||
class="form-check-input"
|
||||
id="set_@set.Value" />
|
||||
<label class="form-check-label" for="set_@set.Value">@set.Text</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<div class="form-group">
|
||||
<label>Format</label>
|
||||
<select asp-for="Format" class="form-control">
|
||||
<option value="doc">Word (.docx)</option>
|
||||
<option value="xls">Excel (.xlsx)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Download</button>
|
||||
<a asp-page="./Index" class="btn btn-secondary">Back to List</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{
|
||||
await Html.RenderPartialAsync("_ValidationScriptsPartial");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Security.Claims;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BindingModels;
|
||||
using YAPContracts.BusinessLogicContracts;
|
||||
using YAPContracts.Enums;
|
||||
using YAPDatabase.Models;
|
||||
using YAPWebApplication.Adapters;
|
||||
|
||||
namespace YAPWebApplication.Pages.Views.Reports
|
||||
{
|
||||
internal class ProductsByProductSetsReportModel : PageModel
|
||||
{
|
||||
private readonly IProductSetAdapter _productSetAdapter;
|
||||
private readonly IReportBusinessLogicContract _report;
|
||||
public ProductsByProductSetsReportModel(IProductSetAdapter productSetAdapter, IReportBusinessLogicContract report)
|
||||
{
|
||||
_productSetAdapter = productSetAdapter;
|
||||
_report = report;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public List<string> SelectedProductSetIds { get; set; } = new();
|
||||
|
||||
public List<SelectListItem> ProductSets { get; set; } = new();
|
||||
|
||||
[BindProperty]
|
||||
public string Format { get; set; } = "doc";
|
||||
public IActionResult OnGet()
|
||||
{
|
||||
LoadFormFields();
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
|
||||
public IActionResult OnPost()
|
||||
{
|
||||
var stream = _report.MakeReportProductsByProductSets(SelectedProductSetIds, Format);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var fileName = $"products_by_sets.{Format}";
|
||||
var contentType = Format == "xls"
|
||||
? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
: "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
|
||||
return File(stream, contentType, fileName);
|
||||
}
|
||||
|
||||
private void LoadFormFields()
|
||||
{
|
||||
ProductSets = _productSetAdapter.GetList()?
|
||||
.Select(s => new SelectListItem { Value = s.Id, Text = s.SetName })
|
||||
.ToList() ?? new();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
@page
|
||||
@model YAPWebApplication.Pages.Views.Reports.PurchasesReportModel
|
||||
@{
|
||||
ViewData["Title"] = "Report: Purchases by date";
|
||||
}
|
||||
|
||||
<h1>Purchases report</h1>
|
||||
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>Start date</label>
|
||||
<input asp-for="DateStart" type="date" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>End date</label>
|
||||
<input asp-for="DateEnd" type="date" class="form-control" />
|
||||
</div>
|
||||
<div class="text-danger">
|
||||
@Html.ValidationSummary(false)
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Show report</button>
|
||||
</form>
|
||||
@if (Model.ReportUrl != null)
|
||||
{
|
||||
<hr />
|
||||
<h3>PDF preview</h3>
|
||||
<iframe src="@Model.ReportUrl" width="100%" height="600px"></iframe>
|
||||
|
||||
<p class="mt-2">
|
||||
<a href="@Model.ReportUrl" class="btn btn-success" download>Download PDF</a>
|
||||
</p>
|
||||
}
|
||||
<form method="post" asp-page-handler="SendEmail">
|
||||
<input type="hidden" asp-for="DateStart" />
|
||||
<input type="hidden" asp-for="DateEnd" />
|
||||
<div class="form-group">
|
||||
<label>Email</label>
|
||||
<input asp-for="RecipientEmail" type="email" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group mt-2">
|
||||
<button type="submit" class="btn btn-success">Send to Email</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if (TempData["Message"] != null)
|
||||
{
|
||||
<div class="alert alert-success mt-2">@TempData["Message"]</div>
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using DocumentFormat.OpenXml.Bibliography;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using System.Security.Claims;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BusinessLogicContracts;
|
||||
using YAPWebApplication.Infrastructure;
|
||||
|
||||
namespace YAPWebApplication.Pages.Views.Reports
|
||||
{
|
||||
internal class PurchasesReportModel : PageModel
|
||||
{
|
||||
private readonly IReportBusinessLogicContract _reportBL;
|
||||
private readonly IEmailService _emailService;
|
||||
private readonly IWorkerAdapter _workerAdapter;
|
||||
|
||||
public PurchasesReportModel(IReportBusinessLogicContract reportBL, IEmailService emailService, IWorkerAdapter workerAdapter)
|
||||
{
|
||||
_reportBL = reportBL;
|
||||
_emailService = emailService;
|
||||
_workerAdapter = workerAdapter;
|
||||
}
|
||||
|
||||
// supporting query string on GET
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public DateTime DateStart { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public DateTime DateEnd { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string RecipientEmail { get; set; } = string.Empty;
|
||||
|
||||
public string? ReportUrl { get; set; }
|
||||
|
||||
public IActionResult OnGet(string? reportFile = null)
|
||||
{
|
||||
if (DateStart == default) DateStart = DateTime.UtcNow.ToLocalTime();
|
||||
if (DateEnd == default) DateEnd = DateTime.UtcNow.ToLocalTime().AddDays(7);
|
||||
|
||||
FillEmail();
|
||||
|
||||
if (!string.IsNullOrEmpty(reportFile))
|
||||
{
|
||||
ReportUrl = $"/reports/{reportFile}";
|
||||
}
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
public IActionResult OnPost()
|
||||
{
|
||||
FillEmail();
|
||||
|
||||
if (DateStart > DateEnd)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "End date must be later than start date!.");
|
||||
return Page();
|
||||
}
|
||||
|
||||
var stream = _reportBL.MakeReportByPurchases(DateStart.ToUniversalTime(), DateEnd.ToUniversalTime());
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var fileName = $"sales_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf";
|
||||
var folderPath = Path.Combine("wwwroot", "reports");
|
||||
Directory.CreateDirectory(folderPath);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
foreach (var file in Directory.GetFiles(folderPath, "*.pdf"))
|
||||
{
|
||||
var creationTime = System.IO.File.GetCreationTime(file);
|
||||
if (creationTime < DateTime.Now.AddDays(-1))
|
||||
{
|
||||
try { System.IO.File.Delete(file); } catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
|
||||
var filePath = Path.Combine(folderPath, fileName);
|
||||
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
|
||||
// PRG: redirecting on GET, to save dates and filename in query
|
||||
return RedirectToPage(new
|
||||
{
|
||||
DateStart = DateStart.ToString("yyyy-MM-dd"),
|
||||
DateEnd = DateEnd.ToString("yyyy-MM-dd"),
|
||||
reportFile = fileName
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostSendEmail()
|
||||
{
|
||||
if (DateStart >= DateEnd)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "End date must be later than start date!");
|
||||
FillEmail();
|
||||
return Page();
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(RecipientEmail))
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Email is required to send report!");
|
||||
FillEmail();
|
||||
return Page();
|
||||
}
|
||||
|
||||
var stream = _reportBL.MakeReportByPurchases(DateStart.ToUniversalTime(), DateEnd.ToUniversalTime());
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
try
|
||||
{
|
||||
await _emailService.SendEmailAsync(
|
||||
RecipientEmail,
|
||||
"Purchases report",
|
||||
$"Report for period {DateStart:dd.MM.yyyy} - {DateEnd:dd.MM.yyyy}",
|
||||
stream,
|
||||
$"sales_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf"
|
||||
);
|
||||
|
||||
TempData["Message"] = "Report sent to Email!";
|
||||
return RedirectToPage(new
|
||||
{
|
||||
DateStart = DateStart.ToString("yyyy-MM-dd"),
|
||||
DateEnd = DateEnd.ToString("yyyy-MM-dd"),
|
||||
reportFile = $"sales_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, $"Failed to send email: {ex.Message}");
|
||||
FillEmail();
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
|
||||
private void FillEmail()
|
||||
{
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var user = _workerAdapter.GetElement(userId);
|
||||
if (!string.IsNullOrWhiteSpace(user?.Email))
|
||||
RecipientEmail = user.Email;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Serilog;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using YAPBusinessLogic.Implementations;
|
||||
using YAPBusinessLogic.OfficePackage;
|
||||
using YAPContracts.AdapterContracts;
|
||||
using YAPContracts.BusinessLogicContracts;
|
||||
using YAPContracts.Infrastructure;
|
||||
@@ -66,6 +67,10 @@ builder.Services.AddTransient<IProductSetBusinessLogicContract, ProductSetBusine
|
||||
builder.Services.AddTransient<IWorkerBusinessLogicContract, WorkerBusinessLogicContract>();
|
||||
builder.Services.AddTransient<IStorekeeperBusinessLogicContract, StorekeeperBusinessLogicContract>();
|
||||
|
||||
builder.Services.AddTransient<BasePdfBuilder, MigraDocPdfBuilder>();
|
||||
builder.Services.AddTransient<BaseWordBuilder, OpenXmlWordBuilder>();
|
||||
builder.Services.AddTransient<BaseExcelBuilder, OpenXmlExcelBuilder>();
|
||||
|
||||
builder.Services.AddTransient<ICommentStorageContract, CommentStorageContract>();
|
||||
builder.Services.AddTransient<IComponentStorageContract, ComponentStorageContract>();
|
||||
builder.Services.AddTransient<IPurchaseStorageContract, PurchaseStorageContract>();
|
||||
@@ -84,6 +89,8 @@ builder.Services.AddTransient<IPurchaseAdapter, PurchaseAdapter>();
|
||||
builder.Services.AddTransient<IWorkerAdapter, WorkerAdapter>();
|
||||
builder.Services.AddTransient<IStorekeeperAdapter, StorekeeperAdapter>();
|
||||
|
||||
builder.Services.AddTransient<IReportBusinessLogicContract, ReportBusinessLogicContract>();
|
||||
builder.Services.AddTransient<IEmailService, EmailService>();
|
||||
|
||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MailKit" Version="4.13.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
|
||||
|
||||
@@ -24,5 +24,13 @@
|
||||
"AllowedHosts": "*",
|
||||
"DatabaseSettings": {
|
||||
"ConnectionString": "Host=127.0.0.1;Port=5432;Database=YAP;Username=postgres;Password=postgres;"
|
||||
},
|
||||
"Email": {
|
||||
"SmtpServer": "smtp.yandex.ru",
|
||||
"SmtpPort": 465,
|
||||
"SmtpUser": "saratov.escaper@yandex.ru",
|
||||
"SmtpPass": "gldtzvjtnfgzhhpu",
|
||||
"FromName": "YAP Mail Service",
|
||||
"FromEmail": "saratov.escaper@yandex.ru"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user