mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-19 15:54:27 +02:00
fix(archives): bulk and auto purge now honour the soft / hard delete choice from #1343 (#1390 follow-up)
Reporter IndividualGhost1905 followed up after the #1378 / #1343 backfill landed and pointed at the next inconsistency: the per- archive delete dialog has had a "Also remove this print from Quick Stats" checkbox since #1343, but the "Purge Old" button and the scheduled daily auto-purge sweeper both ignored that choice and hard-deleted unconditionally. From the user side this looked like "automatically deleted from statistics without any warning" — half- true, and the inconsistency was real either way. The actual current shape (before this fix): - POST /archives/purge -> archive_purge_service.purge_older_than -> ArchiveService.delete_archive (hard). Archive row dropped. Linked PrintLogEntry rows have ON DELETE SET NULL so they survive as orphans with archive_id=NULL. Quick Stats keeps the filament / cost / energy contribution because the log rows are still there, but the archive-list-iterating widgets (Filament Trends, By Material, Color Distribution, Printer Stats) lose the row, and Time Accuracy loses its join target. Visibly inconsistent. - Scheduled _maybe_run_auto_purge -> same code path, same effect. - Single-archive DELETE /archives/{id} -> already takes purge_stats=true|false (default false=soft) and routes either soft_delete_archive (keeps everything, flips deleted_at) or deletes PrintLogEntry rows first + hard-deletes archive. The fix threads the same purge_stats flag through every bulk surface with soft as the default, matching the single-archive default: Backend: - archive_purge_service.purge_older_than(..., purge_stats=False) -> per-row soft_delete_archive when False, per-row PrintLogEntry deletion + delete_archive when True. Each runs in its own session (same pattern the sweeper already used). - preview_purge gains the same kwarg so the eligible-count matches what an actual run would touch: soft mode excludes already-soft-deleted rows, hard mode counts them as eligible for promotion. - get_settings / set_settings now persist archive_auto_purge_stats (default False). _maybe_run_auto_purge reads it on every tick. - ArchivePurgeRequest / ArchivePurgeResponse / ArchivePurgeSettings schemas extended. - Route /archives/purge accepts the body flag, /purge/preview accepts the query param, /purge/settings GET + PUT echo the setting. Frontend: - "Purge old archives" modal: new "Also remove from statistics" checkbox under the preview, unchecked by default. Plumbed into the preview query key + the execute mutation. - Settings -> Archives auto-purge card: matching toggle next to the days slider, disabled when auto-purge itself is off. - api.previewArchivePurge / api.executeArchivePurge accept the flag; ArchivePurgeSettings type gains purge_stats. - All 8 locales (en, de, fr, it, ja, pt-BR, zh-CN, zh-TW) get new purgeStatsLabel / purgeStatsHint / purgeStatsDescription keys, plus rewritten effect / warning copy in archivePurge and archiveAutoPurge to reflect that the default no longer "permanently removes from the database" but instead hides the row + removes files while keeping Quick Stats intact. i18n parity check clean: 4814 keys across all 8 locales, no fallback. Behaviour change for existing users on auto-purge: the sweeper used to hard-delete by default and now soft-deletes by default. After the upgrade those installs start *preserving* more data in Quick Stats rather than losing it — safer direction of the two, but worth the explicit call-out. Anyone who wants the old behaviour ticks the new toggle once and it persists.
This commit is contained in:
@@ -3506,12 +3506,18 @@ export const api = {
|
||||
request<void>(`/archives/${id}${purgeStats ? '?purge_stats=true' : ''}`, { method: 'DELETE' }),
|
||||
|
||||
// ========== Archive auto-purge (#1008 follow-up) ==========
|
||||
previewArchivePurge: (olderThanDays: number) =>
|
||||
request<ArchivePurgePreview>(`/archives/purge/preview?older_than_days=${olderThanDays}`),
|
||||
executeArchivePurge: (olderThanDays: number) =>
|
||||
request<{ deleted: number }>('/archives/purge', {
|
||||
previewArchivePurge: (olderThanDays: number, purgeStats: boolean = false) =>
|
||||
request<ArchivePurgePreview>(
|
||||
`/archives/purge/preview?older_than_days=${olderThanDays}&purge_stats=${purgeStats}`,
|
||||
),
|
||||
// #1390: purgeStats=false (default) soft-deletes each old archive — Quick Stats
|
||||
// preserved, files removed from disk, row hidden via deleted_at. true matches
|
||||
// the single-archive delete's `?purge_stats=true` semantics (hard-deletes the
|
||||
// linked PrintLogEntry rows so the contribution drops from /stats too).
|
||||
executeArchivePurge: (olderThanDays: number, purgeStats: boolean = false) =>
|
||||
request<{ deleted: number; purge_stats: boolean }>('/archives/purge', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ older_than_days: olderThanDays }),
|
||||
body: JSON.stringify({ older_than_days: olderThanDays, purge_stats: purgeStats }),
|
||||
}),
|
||||
getArchivePurgeSettings: () =>
|
||||
request<ArchivePurgeSettings>('/archives/purge/settings'),
|
||||
@@ -5950,6 +5956,10 @@ export interface ArchivePurgePreview {
|
||||
export interface ArchivePurgeSettings {
|
||||
enabled: boolean;
|
||||
days: number;
|
||||
// #1390: when true, bulk-deletes the linked PrintLogEntry rows so the
|
||||
// contribution drops from Quick Stats too. Default false — soft-delete,
|
||||
// Quick Stats preserved.
|
||||
purge_stats: boolean;
|
||||
}
|
||||
|
||||
export interface LibraryFileUploadResponse {
|
||||
|
||||
Reference in New Issue
Block a user