From acdfc2f46d65a75b28fcf83c7b7838313e778b7a Mon Sep 17 00:00:00 2001 From: DmitriyFadin <93384500+DmitriyFadin@users.noreply.github.com> Date: Wed, 30 Sep 2026 17:08:53 +0300 Subject: [PATCH] Use client name and creation date for PDF downloads --- docs/verification.md | 5 +++++ src/TrainingPlanner.Web/Pages/Export.cshtml.cs | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/verification.md b/docs/verification.md index 250292f..75d4c88 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -110,3 +110,8 @@ - Вместо «Открыть видео» выводится полный URL с невидимыми возможностями переноса; адрес гиперссылки остаётся исходным. - Все столбцы после «Примечания», включая заголовки и итоговые значения, выровнены по горизонтальному и вертикальному центру. - Сборка и Docker-обновление успешны. В тестовом PDF проверены полный длинный URL внутри ячейки, неизменный адрес перехода в аннотациях PDF и центрирование числовых ячеек по координатам (отклонение менее 1 pt). Скриншоты не выполнялись; собственные тестовые данные удалены. + +## Имя PDF — 30 сентября 2026 + +- Имя скачиваемого файла: «Имя клиента — dd.MM.yyyy.pdf», дата создания программы без времени, в том же локальном времени сервера, что и история программ. Недопустимые символы имени файла заменяются подчёркиванием. +- Сборка и Docker-обновление успешны. Проверен Content-Disposition с кириллическим именем клиента и форматом даты. Собственные тестовые записи удалены, скриншоты не выполнялись. diff --git a/src/TrainingPlanner.Web/Pages/Export.cshtml.cs b/src/TrainingPlanner.Web/Pages/Export.cshtml.cs index 267551a..9e1f3fe 100644 --- a/src/TrainingPlanner.Web/Pages/Export.cshtml.cs +++ b/src/TrainingPlanner.Web/Pages/Export.cshtml.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using System.Globalization; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; @@ -18,6 +19,9 @@ public class ExportModel(IPlanReader reader, IPlanPdfExporter exporter) : PageMo var client = await reader.GetClientAsync(plan.ClientId, trainerId); if (client == null) return NotFound(); Response.Headers.CacheControl = "no-store"; - return File(exporter.Export(plan, client), "application/pdf", $"training-program-{id}.pdf"); + var clientName = string.Concat(client.Name.Select(character => + char.IsControl(character) || "<>:\"/\\|?*".Contains(character) ? '_' : character)).Trim(); + var createdDate = plan.CreatedAtUtc.ToLocalTime().ToString("dd.MM.yyyy", CultureInfo.InvariantCulture); + return File(exporter.Export(plan, client), "application/pdf", $"{clientName} — {createdDate}.pdf"); } }