Add kontakt_email to job offers
- New kontakt_email TEXT column on jobangebote (+ ALTER TABLE migration) - Accept kontakt_email in POST /api/v1/joboffers (create + upsert) and document it in the OpenAPI spec - Render a mailto: link on the /jobangebote page and include it in the curl example Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+5
-3
@@ -537,6 +537,7 @@ function createExternalApi(deps) {
|
||||
const quelle = sanitizeInput(b.quelle || 'drittanbieter');
|
||||
const externalId = b.external_id != null ? sanitizeInput(String(b.external_id)) : null;
|
||||
const anzeigeDatum = sanitizeInput(b.anzeige_datum || '');
|
||||
const kontaktEmail = sanitizeInput(b.kontakt_email || '');
|
||||
const fields = [
|
||||
sanitizeInput(b.firma),
|
||||
sanitizeInput(b.stelle),
|
||||
@@ -546,6 +547,7 @@ function createExternalApi(deps) {
|
||||
sanitizeInput(b.quelle_url || ''),
|
||||
sanitizeInput(b.art || ''),
|
||||
anzeigeDatum,
|
||||
kontaktEmail,
|
||||
sanitizeInput(b.status || 'offen'),
|
||||
];
|
||||
|
||||
@@ -558,7 +560,7 @@ function createExternalApi(deps) {
|
||||
if (existing) {
|
||||
await dbRun(
|
||||
`UPDATE jobangebote SET firma = ?, stelle = ?, ort = ?, gehalt = ?,
|
||||
beschreibung = ?, quelle_url = ?, art = ?, anzeige_datum = ?, status = ?,
|
||||
beschreibung = ?, quelle_url = ?, art = ?, anzeige_datum = ?, kontakt_email = ?, status = ?,
|
||||
updated_at = CURRENT_TIMESTAMP WHERE id = ?`,
|
||||
[...fields, existing.id]
|
||||
);
|
||||
@@ -569,8 +571,8 @@ function createExternalApi(deps) {
|
||||
|
||||
const result = await dbRun(
|
||||
`INSERT INTO jobangebote
|
||||
(external_id, quelle, firma, stelle, ort, gehalt, beschreibung, quelle_url, art, anzeige_datum, status)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
(external_id, quelle, firma, stelle, ort, gehalt, beschreibung, quelle_url, art, anzeige_datum, kontakt_email, status)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[externalId, quelle, ...fields]
|
||||
);
|
||||
const row = await dbGet('SELECT * FROM jobangebote WHERE id = ?', [result.lastID]);
|
||||
|
||||
@@ -785,6 +785,7 @@ function buildOpenApiSpec(baseUrl = '') {
|
||||
quelle_url: { type: 'string', nullable: true },
|
||||
art: { type: 'string', nullable: true },
|
||||
anzeige_datum: { type: 'string', format: 'date', nullable: true, description: 'Datum der eigentlichen Stellenanzeige (vom Drittanbieter übergeben)' },
|
||||
kontakt_email: { type: 'string', format: 'email', nullable: true, description: 'Kontakt-E-Mail-Adresse der Stelle' },
|
||||
status: { type: 'string', enum: ['offen', 'uebernommen', 'abgelehnt'] },
|
||||
verknuepfte_bewerbung_id: { type: 'integer', nullable: true },
|
||||
created_at: { type: 'string', format: 'date-time' },
|
||||
@@ -805,6 +806,7 @@ function buildOpenApiSpec(baseUrl = '') {
|
||||
quelle_url: { type: 'string' },
|
||||
art: { type: 'string', enum: ART_OPTIONS },
|
||||
anzeige_datum: { type: 'string', format: 'date', description: 'Datum der eigentlichen Stellenanzeige (ISO YYYY-MM-DD)' },
|
||||
kontakt_email: { type: 'string', format: 'email', description: 'Kontakt-E-Mail-Adresse der Stelle' },
|
||||
status: { type: 'string', enum: ['offen', 'uebernommen', 'abgelehnt'], default: 'offen' },
|
||||
},
|
||||
},
|
||||
|
||||
@@ -620,6 +620,7 @@ function initializeDatabase() {
|
||||
quelle_url TEXT,
|
||||
art TEXT,
|
||||
anzeige_datum DATE,
|
||||
kontakt_email TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'offen',
|
||||
verknuepfte_bewerbung_id INTEGER,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
@@ -628,8 +629,9 @@ function initializeDatabase() {
|
||||
FOREIGN KEY (verknuepfte_bewerbung_id) REFERENCES bewerbungen(id) ON DELETE SET NULL
|
||||
)
|
||||
`);
|
||||
// Migration: add anzeige_datum to pre-existing jobangebote tables.
|
||||
// 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', () => {});
|
||||
// Remember the last recipient address per application (prefill).
|
||||
db.run('ALTER TABLE bewerbungen ADD COLUMN email_empfaenger TEXT', () => {});
|
||||
|
||||
|
||||
@@ -71,6 +71,13 @@
|
||||
<span class="truncate"><%= j.quelle_url %></span>
|
||||
</a>
|
||||
<% } %>
|
||||
<% if (j.kontakt_email) { %>
|
||||
<a href="mailto:<%= j.kontakt_email %>"
|
||||
class="inline-flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400 hover:underline mt-1">
|
||||
<svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg>
|
||||
<%= j.kontakt_email %>
|
||||
</a>
|
||||
<% } %>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500 mt-2 flex flex-wrap gap-x-3 gap-y-1">
|
||||
<% if (j.anzeige_datum) { %>
|
||||
<span title="Datum der eigentlichen Stellenanzeige">
|
||||
@@ -156,7 +163,8 @@
|
||||
"beschreibung": "…",
|
||||
"quelle_url": "https://acme.example/job/12345",
|
||||
"art": "Online-Portal",
|
||||
"anzeige_datum": "2026-07-01"
|
||||
"anzeige_datum": "2026-07-01",
|
||||
"kontakt_email": "bewerbung@acme.example"
|
||||
// "created_at" (Einspielung) NICHT mitsenden — wird vom Server automatisch gesetzt.
|
||||
}'</code></pre>
|
||||
<p class="text-xs">Wiederholtes Senden mit derselben <code>quelle</code> + <code>external_id</code> aktualisiert das Angebot (Upsert). Die Doku/Swagger-UI liegt unter <a href="/swagger" class="text-blue-600 dark:text-blue-400 hover:underline">/swagger</a>.</p>
|
||||
|
||||
Reference in New Issue
Block a user