diff --git a/lib/api.js b/lib/api.js
index 1a619b2..6525b4b 100644
--- a/lib/api.js
+++ b/lib/api.js
@@ -614,6 +614,8 @@ function createExternalApi(deps) {
sanitizeInput(b.firma),
sanitizeInput(b.stelle),
sanitizeInput(b.ort || ''),
+ sanitizeInput(b.adresse || ''),
+ sanitizeInput(b.ansprechpartner || ''),
sanitizeInput(b.gehalt || ''),
sanitizeInput(b.beschreibung || ''),
sanitizeInput(b.quelle_url || ''),
@@ -642,7 +644,7 @@ function createExternalApi(deps) {
if (existing) {
await dbRun(
- `UPDATE jobangebote SET firma = ?, stelle = ?, ort = ?, gehalt = ?,
+ `UPDATE jobangebote SET firma = ?, stelle = ?, ort = ?, adresse = ?, ansprechpartner = ?, gehalt = ?,
beschreibung = ?, quelle_url = ?, art = ?, anzeige_datum = ?, kontakt_email = ?, status = ?,
url_norm = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?`,
[...fields, existing.id]
@@ -653,8 +655,8 @@ function createExternalApi(deps) {
const result = await dbRun(
`INSERT INTO jobangebote
- (external_id, quelle, firma, stelle, ort, gehalt, beschreibung, quelle_url, art, anzeige_datum, kontakt_email, status, url_norm)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
+ (external_id, quelle, firma, stelle, ort, adresse, ansprechpartner, gehalt, beschreibung, quelle_url, art, anzeige_datum, kontakt_email, status, url_norm)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[externalId, quelle, ...fields]
);
const row = await dbGet('SELECT * FROM jobangebote WHERE id = ?', [result.lastID]);
diff --git a/lib/openapi.js b/lib/openapi.js
index 1992e2c..c638020 100644
--- a/lib/openapi.js
+++ b/lib/openapi.js
@@ -855,6 +855,8 @@ function buildOpenApiSpec(baseUrl = '') {
firma: { type: 'string' },
stelle: { type: 'string' },
ort: { type: 'string', nullable: true },
+ adresse: { type: 'string', nullable: true, description: 'Anschrift des Arbeitgebers (Straße, Hausnummer, PLZ, Ort)' },
+ ansprechpartner: { type: 'string', nullable: true, description: 'Name des Ansprechpartners für die Bewerbung' },
gehalt: { type: 'string', nullable: true },
beschreibung: { type: 'string', nullable: true },
quelle_url: { type: 'string', nullable: true },
@@ -877,6 +879,8 @@ function buildOpenApiSpec(baseUrl = '') {
firma: { type: 'string' },
stelle: { type: 'string' },
ort: { type: 'string' },
+ adresse: { type: 'string', description: 'Anschrift des Arbeitgebers (Straße, Hausnummer, PLZ, Ort)' },
+ ansprechpartner: { type: 'string', description: 'Name des Ansprechpartners für die Bewerbung' },
gehalt: { type: 'string' },
beschreibung: { type: 'string', description: 'Stellenbeschreibungstext' },
quelle_url: { type: 'string' },
diff --git a/server.js b/server.js
index 1bafe84..f847df4 100644
--- a/server.js
+++ b/server.js
@@ -640,6 +640,8 @@ function initializeDatabase() {
firma TEXT NOT NULL,
stelle TEXT NOT NULL,
ort TEXT,
+ adresse TEXT,
+ ansprechpartner TEXT,
gehalt TEXT,
beschreibung TEXT,
quelle_url TEXT,
@@ -657,6 +659,8 @@ function initializeDatabase() {
// Migration: add columns to pre-existing jobangebote tables.
db.run('ALTER TABLE jobangebote ADD COLUMN anzeige_datum DATE', () => {});
db.run('ALTER TABLE jobangebote ADD COLUMN kontakt_email TEXT', () => {});
+ db.run('ALTER TABLE jobangebote ADD COLUMN adresse TEXT', () => {});
+ db.run('ALTER TABLE jobangebote ADD COLUMN ansprechpartner TEXT', () => {});
// Normalized URL for URL-based de-duplication of offers (see lib/blacklist).
db.run('ALTER TABLE jobangebote ADD COLUMN url_norm TEXT', () => {
// Backfill url_norm for rows ingested before this column existed.
@@ -1726,11 +1730,23 @@ initializeDatabase().then(() => {
angebot.quelle ? `Importiert via: ${angebot.quelle}` : null,
].filter(Boolean);
+ // Employer address (street, house number, city) and contact person go into
+ // the AI notes so the LLM can use them for the letter's Anschriftfeld and
+ // salutation.
+ let anschrift = (angebot.adresse || '').trim();
+ if (angebot.ort && !anschrift.toLowerCase().includes(String(angebot.ort).toLowerCase())) {
+ anschrift = anschrift ? `${anschrift}, ${angebot.ort}` : String(angebot.ort);
+ }
+ const llmNotizen = [
+ anschrift ? `Anschrift des Arbeitgebers: ${anschrift}` : null,
+ angebot.ansprechpartner ? `Ansprechpartner: ${angebot.ansprechpartner}` : null,
+ ].filter(Boolean).join('\n');
+
const result = await dbRun(
`INSERT INTO bewerbungen
(datum, firma, stelle, art, status, notizen, ort, stellenbeschreibung,
- quelle_url, email_empfaenger, generierung_status)
- VALUES (?, ?, ?, ?, 'Entwurf', ?, ?, ?, ?, ?, 'nicht_gestartet')`,
+ quelle_url, email_empfaenger, llm_notizen, generierung_status)
+ VALUES (?, ?, ?, ?, 'Entwurf', ?, ?, ?, ?, ?, ?, 'nicht_gestartet')`,
[
datum,
sanitizeInput(angebot.firma),
@@ -1741,6 +1757,7 @@ initializeDatabase().then(() => {
angebot.beschreibung || '',
angebot.quelle_url || '',
angebot.kontakt_email || '',
+ llmNotizen,
]
);
@@ -1799,7 +1816,7 @@ initializeDatabase().then(() => {
const b = req.body || {};
const quelleUrl = sanitizeInput(b.quelle_url || '');
await dbRun(
- `UPDATE jobangebote SET firma = ?, stelle = ?, ort = ?, gehalt = ?,
+ `UPDATE jobangebote SET firma = ?, stelle = ?, ort = ?, adresse = ?, ansprechpartner = ?, gehalt = ?,
beschreibung = ?, kontakt_email = ?, quelle_url = ?, anzeige_datum = ?,
url_norm = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?`,
@@ -1807,6 +1824,8 @@ initializeDatabase().then(() => {
sanitizeInput((b.firma || '').trim()) || angebot.firma,
sanitizeInput((b.stelle || '').trim()) || angebot.stelle,
sanitizeInput(b.ort || ''),
+ sanitizeInput(b.adresse || ''),
+ sanitizeInput(b.ansprechpartner || ''),
sanitizeInput(b.gehalt || ''),
sanitizeInput(b.beschreibung || ''),
sanitizeInput(b.kontakt_email || ''),
diff --git a/views/bewerbung.ejs b/views/bewerbung.ejs
index 13c8e67..93102fc 100644
--- a/views/bewerbung.ejs
+++ b/views/bewerbung.ejs
@@ -360,7 +360,8 @@
Versand über <%= mailFrom %>. Empfängeradresse eingeben, Betreff und Text prüfen,
Anhänge auswählen und senden.