Pdf reports preview + cleanup

This commit is contained in:
2025-09-18 17:33:00 +04:00
parent b96c2b1557
commit 0f4d9a83d3
23 changed files with 121 additions and 818 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
@model YAPWebApplication.Pages.Views.Comments.IndexModel
@{
ViewData["Title"] = "Index";
ViewData["Title"] = "Comments";
}
<h1>Comments</h1>

View File

@@ -2,10 +2,10 @@
@model YAPWebApplication.Pages.Views.Components.IndexModel
@{
ViewData["Title"] = "Index";
ViewData["Title"] = "Product Orders";
}
<h1>Index</h1>
<h1>Product Orders</h1>
@if (User.IsInRole("Storekeeper"))
{
<p>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"))
{

View File

@@ -1,17 +1,28 @@
@page
@model YAPWebApplication.Pages.Views.Reports.ComponentsReportModel
@{
ViewData["Title"] = "Report: Components by date";
}
<h1>Отчёт по комплектующим</h1>
<h1>Components report</h1>
<form method="post">
<div class="form-group">
<label>Дата начала</label>
<label>Start date</label>
<input asp-for="DateStart" type="date" class="form-control" />
</div>
<div class="form-group">
<label>Дата окончания</label>
<label>End date</label>
<input asp-for="DateEnd" type="date" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Скачать PDF</button>
</form>
<button type="submit" class="btn btn-primary">Download PDF</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>
}

View File

@@ -1,3 +1,4 @@
using DocumentFormat.OpenXml.Bibliography;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using YAPContracts.BusinessLogicContracts;
@@ -19,12 +20,47 @@ namespace YAPWebApplication.Pages.Views.Reports
[BindProperty]
public DateTime DateEnd { get; set; } = DateTime.UtcNow.ToLocalTime().AddDays(7);
public string? ReportUrl { get; set; }
public IActionResult OnPost()
{
var stream = _reportBL.MakeReportByComponents(DateStart.ToUniversalTime(), DateEnd.ToUniversalTime());
if (DateStart > DateEnd)
{
ModelState.AddModelError(string.Empty, "<22><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.");
return Page();
}
var stream = _reportBL.MakeReportByPurchases(DateStart.ToUniversalTime(), DateEnd.ToUniversalTime());
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/pdf", $"components_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf");
var fileName = $"sales_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
{
// ignoring exceptions during file deletion
}
}
}
var filePath = Path.Combine(folderPath, fileName);
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
stream.CopyTo(fs);
}
ReportUrl = $"/reports/{fileName}";
return Page();
}
}
}

View File

@@ -1,7 +1,7 @@
@page
@model YAPWebApplication.Pages.Views.Reports.ProductSetsByProductsReportModel
@{
ViewData["Title"] = "Report: sets by products";
ViewData["Title"] = "Report: Sets by Products";
}
<h1>Report: sets by products</h1>

View File

@@ -1,7 +1,7 @@
@page
@model YAPWebApplication.Pages.Views.Reports.ProductsByProductSetsReportModel
@{
ViewData["Title"] = "Products By Product Sets Report";
ViewData["Title"] = "Report: Products by Sets";
}
<h1>Products By Product Sets Report</h1>

View File

@@ -4,16 +4,29 @@
ViewData["Title"] = "Report: Purchases by date";
}
<h1>Отчёт по продажам</h1>
<h1>Purchases report</h1>
<form method="post">
<div class="form-group">
<label>Дата начала</label>
<label>Start date</label>
<input asp-for="DateStart" type="date" class="form-control" />
</div>
<div class="form-group">
<label>Дата окончания</label>
<label>End date</label>
<input asp-for="DateEnd" type="date" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Скачать PDF</button>
<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>
}

View File

@@ -1,3 +1,4 @@
using DocumentFormat.OpenXml.Bibliography;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using YAPContracts.BusinessLogicContracts;
@@ -19,12 +20,47 @@ namespace YAPWebApplication.Pages.Views.Reports
[BindProperty]
public DateTime DateEnd { get; set; } = DateTime.UtcNow.ToLocalTime().AddDays(7);
public string? ReportUrl { get; set; }
public IActionResult OnPost()
{
if (DateStart > DateEnd)
{
ModelState.AddModelError(string.Empty, "<22><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.");
return Page();
}
var stream = _reportBL.MakeReportByPurchases(DateStart.ToUniversalTime(), DateEnd.ToUniversalTime());
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/pdf", $"sales_report_{DateStart:yyyyMMdd}_{DateEnd:yyyyMMdd}.pdf");
var fileName = $"sales_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
{
// ignoring exceptions during file deletion
}
}
}
var filePath = Path.Combine(folderPath, fileName);
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
stream.CopyTo(fs);
}
ReportUrl = $"/reports/{fileName}";
return Page();
}
}
}