PDF-Export: kompakte Tabelle, Filter nach letztem Status-Datum
Verbose Blöcke (Notizen + kompletter Verlauf) durch eine autoTable ersetzt: eine Zeile pro Bewerbung mit Datum, Firma, Stelle, Art und letztem Status (farbiges Badge). Export filtert/datiert nun nach dem effektiven Datum, also der letzten Statusaenderung – eine im Juni gesendete, im Juli zum Gespraech gewordene Bewerbung erscheint dadurch im Juli-Export. Modal-Auswahl nutzt dieselben effektiven Monate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -917,12 +917,29 @@ initializeDatabase().then(() => {
|
||||
|
||||
// Get available months/years for filter
|
||||
const availableMonths = await dbAll(`
|
||||
SELECT DISTINCT strftime("%Y-%m", datum) as yearmonth,
|
||||
strftime("%m", datum) as month,
|
||||
SELECT DISTINCT strftime("%Y-%m", datum) as yearmonth,
|
||||
strftime("%m", datum) as month,
|
||||
strftime("%Y", datum) as year
|
||||
FROM bewerbungen ORDER BY datum DESC
|
||||
`);
|
||||
|
||||
|
||||
// Months/years for the PDF export, keyed by the effective date (last status
|
||||
// change) so a period like Juli 2026 is selectable even when the underlying
|
||||
// application was created in an earlier month.
|
||||
const exportMonths = await dbAll(`
|
||||
SELECT DISTINCT strftime("%Y-%m", eff) as yearmonth,
|
||||
strftime("%m", eff) as month,
|
||||
strftime("%Y", eff) as year
|
||||
FROM (
|
||||
SELECT COALESCE(
|
||||
(SELECT MAX(date(sv.datum)) FROM status_verlauf sv WHERE sv.bewerbung_id = b.id),
|
||||
date(b.datum)
|
||||
) AS eff
|
||||
FROM bewerbungen b
|
||||
)
|
||||
ORDER BY yearmonth DESC
|
||||
`);
|
||||
|
||||
res.render('index', {
|
||||
applications,
|
||||
settings,
|
||||
@@ -932,6 +949,7 @@ initializeDatabase().then(() => {
|
||||
byStatus
|
||||
},
|
||||
availableMonths,
|
||||
exportMonths,
|
||||
currentFilter: { month, year },
|
||||
kommendeTermine,
|
||||
caldavTz: caldav.TZ,
|
||||
@@ -1168,19 +1186,31 @@ initializeDatabase().then(() => {
|
||||
try {
|
||||
const { month, year } = req.query;
|
||||
|
||||
let query = 'SELECT * FROM bewerbungen ORDER BY datum DESC';
|
||||
// Effektives Datum einer Bewerbung = Datum ihrer letzten Statusänderung
|
||||
// (fällt auf das Bewerbungsdatum zurück, wenn es keinen Verlauf gibt). Der
|
||||
// Monatsexport listet eine Bewerbung im Monat ihres LETZTEN Status: Eine im
|
||||
// Juni gesendete Bewerbung, die im Juli zum Vorstellungsgespräch wird,
|
||||
// erscheint dadurch im Export für Juli.
|
||||
const base = `
|
||||
SELECT b.*, COALESCE(
|
||||
(SELECT MAX(date(sv.datum)) FROM status_verlauf sv WHERE sv.bewerbung_id = b.id),
|
||||
date(b.datum)
|
||||
) AS eff_datum
|
||||
FROM bewerbungen b
|
||||
`;
|
||||
let query = `SELECT * FROM (${base}) ORDER BY eff_datum DESC`;
|
||||
const params = [];
|
||||
|
||||
if (month && year) {
|
||||
query = 'SELECT * FROM bewerbungen WHERE strftime("%m", datum) = ? AND strftime("%Y", datum) = ? ORDER BY datum DESC';
|
||||
query = `SELECT * FROM (${base}) WHERE strftime("%m", eff_datum) = ? AND strftime("%Y", eff_datum) = ? ORDER BY eff_datum DESC`;
|
||||
params.push(month.padStart(2, '0'), year);
|
||||
} else if (month) {
|
||||
// A month without a year must still restrict the export to that month —
|
||||
// never fall through to exporting every application.
|
||||
query = 'SELECT * FROM bewerbungen WHERE strftime("%m", datum) = ? ORDER BY datum DESC';
|
||||
query = `SELECT * FROM (${base}) WHERE strftime("%m", eff_datum) = ? ORDER BY eff_datum DESC`;
|
||||
params.push(month.padStart(2, '0'));
|
||||
} else if (year) {
|
||||
query = 'SELECT * FROM bewerbungen WHERE strftime("%Y", datum) = ? ORDER BY datum DESC';
|
||||
query = `SELECT * FROM (${base}) WHERE strftime("%Y", eff_datum) = ? ORDER BY eff_datum DESC`;
|
||||
params.push(year);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user