Files
ReifenSpaeth/Lagerbestand/Services/StorageRowPdfService.cs
T

185 lines
6.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Lagerbestand.Models;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace Lagerbestand.Services;
public interface IStorageRowPdfService
{
/// <summary>
/// Generates a printable A4 inventory sheet for one shelf row (Area + Row).
/// </summary>
byte[] GenerateRowPdf(AreaType area, int row, IReadOnlyList<StorageLocation> locations);
}
public class StorageRowPdfService : IStorageRowPdfService
{
private static readonly string HeaderBackground = Colors.Grey.Lighten3;
private static readonly string BorderColor = Colors.Grey.Medium;
public byte[] GenerateRowPdf(AreaType area, int row, IReadOnlyList<StorageLocation> locations)
{
var rowLocations = locations
.Where(l => l.Area == area && l.Row == row)
.ToList();
var occupied = rowLocations.Count(l => l.IsOccupied);
var total = StorageLocation.PositionsPerSlot * StorageLocation.MaxSlot;
var printedAt = DateTime.Now;
var document = Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(1.5f, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontSize(9));
page.Header()
.PaddingBottom(12)
.AlignCenter()
.Text($"{area.GetDisplayName()} – Regal {row}")
.Bold()
.FontSize(20);
page.Content().Row(r =>
{
r.RelativeItem().Column(col =>
{
col.Spacing(14);
col.Item().Element(c => RenderPositionTable(c, area, row, ShelfPosition.LinksOben, rowLocations));
col.Item().Element(c => RenderPositionTable(c, area, row, ShelfPosition.LinksUnten, rowLocations));
});
r.ConstantItem(14);
r.RelativeItem().Column(col =>
{
col.Spacing(14);
col.Item().Element(c => RenderPositionTable(c, area, row, ShelfPosition.RechtsOben, rowLocations));
col.Item().Element(c => RenderPositionTable(c, area, row, ShelfPosition.RechtsUnten, rowLocations));
});
});
page.Footer()
.PaddingTop(10)
.Row(f =>
{
f.RelativeItem().Text($"Gedruckt am {printedAt:dd.MM.yyyy HH:mm}").FontSize(8).FontColor(Colors.Grey.Darken1);
f.RelativeItem().AlignRight().Text($"{occupied} / {total} belegt").FontSize(8).FontColor(Colors.Grey.Darken1);
});
});
});
return document.GeneratePdf();
}
private static void RenderPositionTable(IContainer container, AreaType area, int row, ShelfPosition position, List<StorageLocation> rowLocations)
{
var bySlot = rowLocations
.Where(l => l.Position == position)
.GroupBy(l => l.SlotNumber)
.ToDictionary(g => g.Key, g => g.First());
container.Column(col =>
{
col.Spacing(4);
col.Item().Text(position.GetDisplayName()).Bold().FontSize(11);
col.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(28);
columns.ConstantColumn(34);
columns.RelativeColumn(3);
columns.RelativeColumn(2);
columns.ConstantColumn(44);
});
table.Header(header =>
{
header.Cell().Element(HeaderCell).Text("Platz");
header.Cell().Element(HeaderCell).Text("Code");
header.Cell().Element(HeaderCell).Text("Kunde/Inhalt");
header.Cell().Element(HeaderCell).Text("Fahrzeug");
header.Cell().Element(HeaderCell).Text("Saison");
});
for (var slot = StorageLocation.MinSlot; slot <= StorageLocation.MaxSlot; slot++)
{
bySlot.TryGetValue(slot, out var location);
var code = location?.Code ?? $"{(int)area}{row}{(int)position}{slot}";
string content, vehicle, season;
var muted = false;
if (location is { IsOccupied: true, OccupiedTireStack: not null })
{
var stack = location.OccupiedTireStack;
content = stack.Customer?.FullName ?? stack.CatalogItem?.Name ?? "Lager";
vehicle = stack.Vehicle?.ShortName ?? "–";
season = SeasonText(stack.Season);
}
else if (location is { IsOccupied: true })
{
content = "Belegt";
vehicle = "–";
season = "–";
}
else if (location is { IsAvailable: false })
{
content = "Gesperrt";
vehicle = "–";
season = "–";
muted = true;
}
else
{
content = "Frei";
vehicle = "–";
season = "–";
muted = true;
}
table.Cell().Element(BodyCell).Text(slot.ToString());
table.Cell().Element(BodyCell).Text(code);
table.Cell().Element(BodyCell).Text(t => Styled(t.Span(content), muted));
table.Cell().Element(BodyCell).Text(t => Styled(t.Span(vehicle), muted));
table.Cell().Element(BodyCell).Text(t => Styled(t.Span(season), muted));
}
});
});
}
private static void Styled(TextSpanDescriptor span, bool muted)
{
if (muted)
span.FontColor(Colors.Grey.Medium).Italic();
}
private static string SeasonText(TireSeason season) => season switch
{
TireSeason.Sommer => "Sommer",
TireSeason.Winter => "Winter",
TireSeason.Allrad => "Ganzjahr",
_ => season.ToString()
};
private static IContainer HeaderCell(IContainer container) => container
.Background(HeaderBackground)
.Border(0.5f)
.BorderColor(BorderColor)
.PaddingVertical(3)
.PaddingHorizontal(4)
.DefaultTextStyle(x => x.Bold().FontSize(8));
private static IContainer BodyCell(IContainer container) => container
.Border(0.5f)
.BorderColor(BorderColor)
.PaddingVertical(3)
.PaddingHorizontal(4)
.DefaultTextStyle(x => x.FontSize(8));
}