166 lines
5.7 KiB
C#
166 lines
5.7 KiB
C#
|
|
using SSPCTester.Logic.Models;
|
||
|
|
using System.Text.Json;
|
||
|
|
using System.Text.Json.Serialization;
|
||
|
|
|
||
|
|
namespace SSPCTester.Logic.Report;
|
||
|
|
|
||
|
|
public enum ReportOutputFormat
|
||
|
|
{
|
||
|
|
Pdf,
|
||
|
|
Word,
|
||
|
|
Both
|
||
|
|
}
|
||
|
|
|
||
|
|
public static class ReportFileHelper
|
||
|
|
{
|
||
|
|
public const string DefaultTemplate = "report_{yyyyMMdd_HHmmss}.pdf";
|
||
|
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
||
|
|
{
|
||
|
|
WriteIndented = true,
|
||
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||
|
|
};
|
||
|
|
|
||
|
|
public static string ResolveFileName(Project project, DateTime now)
|
||
|
|
=> ResolveFileName(project, now, ".pdf");
|
||
|
|
|
||
|
|
public static string ResolveFileName(Project project, DateTime now, string extension)
|
||
|
|
{
|
||
|
|
string template = string.IsNullOrWhiteSpace(project.Report.FileName)
|
||
|
|
? DefaultTemplate
|
||
|
|
: project.Report.FileName.Trim();
|
||
|
|
extension = NormalizeExtension(extension);
|
||
|
|
|
||
|
|
string date = now.ToString("yyyyMMdd");
|
||
|
|
string dateTime = now.ToString("yyyyMMdd_HHmmss");
|
||
|
|
string value = template
|
||
|
|
.Replace("{ProjectName}", project.Name ?? "", StringComparison.OrdinalIgnoreCase)
|
||
|
|
.Replace("{ProductName}", project.Dut.ProductName ?? "", StringComparison.OrdinalIgnoreCase)
|
||
|
|
.Replace("{Model}", project.Dut.Model ?? "", StringComparison.OrdinalIgnoreCase)
|
||
|
|
.Replace("{SerialNumber}", project.Dut.SerialNumber ?? "", StringComparison.OrdinalIgnoreCase)
|
||
|
|
.Replace("{yyyyMMdd_HHmmss}", dateTime, StringComparison.OrdinalIgnoreCase)
|
||
|
|
.Replace("{DateTime}", dateTime, StringComparison.OrdinalIgnoreCase)
|
||
|
|
.Replace("{yyyyMMdd}", date, StringComparison.OrdinalIgnoreCase)
|
||
|
|
.Replace("{Date}", date, StringComparison.OrdinalIgnoreCase);
|
||
|
|
|
||
|
|
value = MakeSafeFileName(value);
|
||
|
|
if (string.IsNullOrWhiteSpace(value))
|
||
|
|
value = $"report_{dateTime}{extension}";
|
||
|
|
value = Path.ChangeExtension(value, extension);
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static ReportOutputFormat ParseFormat(string? value)
|
||
|
|
{
|
||
|
|
if (Enum.TryParse<ReportOutputFormat>(value, ignoreCase: true, out var format))
|
||
|
|
return format;
|
||
|
|
return ReportOutputFormat.Pdf;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static IReadOnlyList<ReportFileDescriptor> EnumerateReportFiles(
|
||
|
|
string? directory,
|
||
|
|
ReportOutputFormat format)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(directory) || !Directory.Exists(directory))
|
||
|
|
return Array.Empty<ReportFileDescriptor>();
|
||
|
|
|
||
|
|
string[] patterns = format switch
|
||
|
|
{
|
||
|
|
ReportOutputFormat.Word => new[] { "*.docx" },
|
||
|
|
ReportOutputFormat.Both => new[] { "*.pdf", "*.docx" },
|
||
|
|
_ => new[] { "*.pdf" }
|
||
|
|
};
|
||
|
|
|
||
|
|
return patterns
|
||
|
|
.SelectMany(pattern => Directory.EnumerateFiles(directory, pattern, SearchOption.TopDirectoryOnly))
|
||
|
|
.Select(path => new FileInfo(path))
|
||
|
|
.OrderByDescending(file => file.LastWriteTime)
|
||
|
|
.Select(file => new ReportFileDescriptor(
|
||
|
|
file.FullName,
|
||
|
|
file.Name,
|
||
|
|
file.LastWriteTime,
|
||
|
|
file.Extension.Equals(".pdf", StringComparison.OrdinalIgnoreCase)
|
||
|
|
? ReportFileKind.Pdf
|
||
|
|
: ReportFileKind.Word))
|
||
|
|
.ToArray();
|
||
|
|
}
|
||
|
|
|
||
|
|
public static IReadOnlyList<ReportFileDescriptor> EnumeratePdfFiles(string? directory)
|
||
|
|
{
|
||
|
|
return EnumerateReportFiles(directory, ReportOutputFormat.Pdf);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static string BuildInfoPath(string outputPath) =>
|
||
|
|
Path.Combine(
|
||
|
|
Path.GetDirectoryName(outputPath) ?? "",
|
||
|
|
Path.GetFileNameWithoutExtension(outputPath) + ".reportinfo.json");
|
||
|
|
|
||
|
|
public static void SaveInfo(ReportInfo info, string infoPath)
|
||
|
|
{
|
||
|
|
Directory.CreateDirectory(Path.GetDirectoryName(infoPath)!);
|
||
|
|
File.WriteAllText(infoPath, JsonSerializer.Serialize(info, JsonOptions));
|
||
|
|
}
|
||
|
|
|
||
|
|
public static ReportInfo? LoadInfoForReport(string reportPath)
|
||
|
|
{
|
||
|
|
string infoPath = BuildInfoPath(reportPath);
|
||
|
|
if (!File.Exists(infoPath)) return null;
|
||
|
|
return JsonSerializer.Deserialize<ReportInfo>(File.ReadAllText(infoPath), JsonOptions);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string MakeSafeFileName(string value)
|
||
|
|
{
|
||
|
|
var invalid = Path.GetInvalidFileNameChars();
|
||
|
|
var chars = value
|
||
|
|
.Select(c => invalid.Contains(c) ? '_' : c)
|
||
|
|
.ToArray();
|
||
|
|
return new string(chars).Trim(' ', '.');
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string NormalizeExtension(string extension)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(extension)) return ".pdf";
|
||
|
|
extension = extension.Trim();
|
||
|
|
return extension.StartsWith('.') ? extension : "." + extension;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public enum ReportFileKind
|
||
|
|
{
|
||
|
|
Pdf,
|
||
|
|
Word
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed record ReportFileDescriptor(
|
||
|
|
string FullPath,
|
||
|
|
string DisplayName,
|
||
|
|
DateTime LastWriteTime,
|
||
|
|
ReportFileKind Kind = ReportFileKind.Pdf)
|
||
|
|
{
|
||
|
|
public bool IsPdf => Kind == ReportFileKind.Pdf;
|
||
|
|
public bool IsWord => Kind == ReportFileKind.Word;
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed class ReportInfo
|
||
|
|
{
|
||
|
|
public string ProjectName { get; set; } = "";
|
||
|
|
public string ProductName { get; set; } = "";
|
||
|
|
public string Model { get; set; } = "";
|
||
|
|
public string SerialNumber { get; set; } = "";
|
||
|
|
public DateTime GeneratedAt { get; set; }
|
||
|
|
public string Format { get; set; } = "";
|
||
|
|
public string? PdfPath { get; set; }
|
||
|
|
public string? WordPath { get; set; }
|
||
|
|
public string OverallStatus { get; set; } = "";
|
||
|
|
public ReportSectionInfo Sections { get; set; } = new();
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed class ReportSectionInfo
|
||
|
|
{
|
||
|
|
public bool Cover { get; set; }
|
||
|
|
public bool Basic { get; set; }
|
||
|
|
public bool Curve { get; set; }
|
||
|
|
public bool Power { get; set; }
|
||
|
|
public bool Protect { get; set; }
|
||
|
|
}
|