feat: Chemikalien-Recherche über lokale RiSU-Stoffliste (kein KI-Aufruf mehr)
Ersetzt den ursprünglichen KI-Websuche-Ansatz (GESTIS scheiterte sowohl über Websuche als auch über direkten API-Zugriff an fehlenden schulspezifischen Tätigkeitsbeschränkungen) durch einen reinen lokalen Datenbank-Lookup gegen die offizielle RiSU-Stoffliste (1764 Stoffe inkl. Tätigkeitsbeschränkungs-Codes, Legende zur Abfragezeit übersetzt statt in die Datenbank gebacken). Keine KI-Kosten, keine Drittanbieter-Abhängigkeit mehr für diese Funktion. HazardSubstance.AgeRestriction zu ActivityRestriction umbenannt, da die Tätigkeitsbeschränkung mehr abdeckt als reine Altersgrenzen. Details und verworfene Zwischenstände in TODO.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,7 +88,8 @@ public sealed record HazardAssessmentPrintData(
|
||||
bool IsAiAssisted);
|
||||
|
||||
public sealed record HazardSubstancePrintRow(
|
||||
string Name, string Amount, string Pictograms, string HStatements, string PStatements);
|
||||
string Name, string Cas, string Amount, string Pictograms, string SignalWord,
|
||||
string HStatements, string PStatements, string ActivityRestriction);
|
||||
|
||||
/// <summary>
|
||||
/// PDF-Erzeugung über QuestPDF (11.3). Liefert fertige Bytes - der Speicherdialog läuft wie bei
|
||||
@@ -380,7 +381,7 @@ public sealed class PdfExportService
|
||||
if (!string.IsNullOrWhiteSpace(data.Procedure))
|
||||
column.Item().Element(c => TextSection(c, "Durchführung", data.Procedure));
|
||||
if (data.Substances.Count > 0)
|
||||
column.Item().Element(c => SubstanceTable(c, data.Substances));
|
||||
column.Item().Element(c => SubstanceBlocks(c, data.Substances));
|
||||
if (data.Hazards.Count > 0)
|
||||
column.Item().Element(c => BulletSection(c, "Gefährdungen", data.Hazards));
|
||||
if (data.ProtectiveMeasures.Count > 0)
|
||||
@@ -419,37 +420,43 @@ public sealed class PdfExportService
|
||||
column.Item().Text($"• {item}");
|
||||
});
|
||||
|
||||
private static void SubstanceTable(IContainer container, IReadOnlyList<HazardSubstancePrintRow> rows) =>
|
||||
/// Eigener Block je Gefahrstoff statt einer engen Tabelle — bei sieben Datenpunkten pro Stoff
|
||||
/// (inkl. CAS, Signalwort, Altersbeschränkung) wäre eine Tabelle auf A4-Hochformat zu schmal
|
||||
/// für lesbare H-/P-Satz-Texte.
|
||||
private static void SubstanceBlocks(IContainer container, IReadOnlyList<HazardSubstancePrintRow> rows) =>
|
||||
container.Column(column =>
|
||||
{
|
||||
column.Spacing(6);
|
||||
column.Item().Text("Gefahrstoffe").FontSize(11).SemiBold();
|
||||
column.Item().Table(table =>
|
||||
foreach (var row in rows)
|
||||
column.Item().Element(c => SubstanceBlock(c, row));
|
||||
});
|
||||
|
||||
private static void SubstanceBlock(IContainer container, HazardSubstancePrintRow row) =>
|
||||
container.Border(0.8f).BorderColor(Colors.Grey.Lighten2).Padding(6).Column(block =>
|
||||
{
|
||||
block.Spacing(2);
|
||||
block.Item().Row(header =>
|
||||
{
|
||||
table.ColumnsDefinition(columns =>
|
||||
header.RelativeItem().Text(text =>
|
||||
{
|
||||
columns.RelativeColumn(2f);
|
||||
columns.RelativeColumn(1f);
|
||||
columns.RelativeColumn(1.3f);
|
||||
columns.RelativeColumn(2f);
|
||||
columns.RelativeColumn(2f);
|
||||
text.Span(row.Name).SemiBold();
|
||||
if (!string.IsNullOrWhiteSpace(row.Cas)) text.Span($" · CAS {row.Cas}").FontColor(Colors.Grey.Darken1);
|
||||
if (!string.IsNullOrWhiteSpace(row.Amount)) text.Span($" · {row.Amount}").FontColor(Colors.Grey.Darken1);
|
||||
});
|
||||
table.Header(header =>
|
||||
{
|
||||
header.Cell().Element(HeaderCell).Text("Stoff").SemiBold();
|
||||
header.Cell().Element(HeaderCell).Text("Menge").SemiBold();
|
||||
header.Cell().Element(HeaderCell).Text("GHS").SemiBold();
|
||||
header.Cell().Element(HeaderCell).Text("H-Sätze").SemiBold();
|
||||
header.Cell().Element(HeaderCell).Text("P-Sätze").SemiBold();
|
||||
});
|
||||
foreach (var row in rows)
|
||||
{
|
||||
table.Cell().Element(BodyCell).Text(row.Name);
|
||||
table.Cell().Element(BodyCell).Text(row.Amount);
|
||||
table.Cell().Element(BodyCell).Text(row.Pictograms);
|
||||
table.Cell().Element(BodyCell).Text(row.HStatements);
|
||||
table.Cell().Element(BodyCell).Text(row.PStatements);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(row.SignalWord))
|
||||
header.ConstantItem(70).AlignRight().Text(row.SignalWord).SemiBold()
|
||||
.FontColor(Colors.Red.Darken2);
|
||||
});
|
||||
if (!string.IsNullOrWhiteSpace(row.Pictograms))
|
||||
block.Item().Text($"GHS: {row.Pictograms}").FontSize(8).FontColor(Colors.Grey.Darken1);
|
||||
if (!string.IsNullOrWhiteSpace(row.HStatements))
|
||||
block.Item().Text($"H-Sätze: {row.HStatements}");
|
||||
if (!string.IsNullOrWhiteSpace(row.PStatements))
|
||||
block.Item().Text($"P-Sätze: {row.PStatements}");
|
||||
if (!string.IsNullOrWhiteSpace(row.ActivityRestriction))
|
||||
block.Item().Text($"Tätigkeitsbeschränkung: {row.ActivityRestriction}").SemiBold()
|
||||
.FontColor(Colors.Orange.Darken3);
|
||||
});
|
||||
|
||||
/// <summary>Horizontaler Balken, 0-100 % der verfügbaren Zellenbreite (max. 150pt).</summary>
|
||||
|
||||
Reference in New Issue
Block a user