Post-print outcome confirmation: good/reject verdicts, one-tap links, yield stats (#3047)

This commit is contained in:
Thomansky
2026-09-26 15:37:19 +02:00
committed by GitHub
parent 4e83751f71
commit 44c7e6fb39
75 changed files with 5752 additions and 74 deletions
+40
View File
@@ -790,6 +790,9 @@ export interface ArchivePrinterMedia {
warnings: Array<'printer_missing' | 'timelapse_unavailable' | 'ipcam_unavailable' | 'printer_files_forbidden'>;
}
/** How a post-print outcome verdict reached the archive (#1898). */
export type VerdictSource = 'dialog' | 'link' | 'plate_clear' | 'printer_card' | 'api' | 'reaction';
export interface Archive {
id: number;
printer_id: number | null;
@@ -836,6 +839,13 @@ export interface Archive {
cost: number | null;
photos: string[] | null;
failure_reason: string | null;
// Post-print outcome confirmation (#1898)
user_verdict: 'good' | 'reject' | null;
// How the verdict arrived; 'reaction' is written by the Telegram reaction
// handler (#3046) and is labelled here so it reads correctly once that lands.
user_verdict_source: VerdictSource | null;
user_verdict_at: string | null;
confirm_requested: boolean;
quantity: number;
energy_kwh: number | null;
energy_cost: number | null;
@@ -930,6 +940,11 @@ export interface FailureAnalysis {
total_prints: number;
failed_prints: number;
failure_rate: number;
// Quality dimension (#1898): completed prints the user rejected. Optional
// so a frontend build against an older backend degrades gracefully.
rejected_prints?: number;
yield_rate?: number;
rejects_by_reason?: Record<string, number>;
failures_by_reason: Record<string, number>;
failures_by_filament: Record<string, number>;
failures_by_printer: Record<string, number>;
@@ -1457,6 +1472,12 @@ export interface AppSettings {
default_layer_inspect: boolean;
default_timelapse: boolean;
default_nozzle_offset_cali: CalibrationMode;
// Default for the per-job "ask for outcome afterwards" toggle (#1898)
default_confirm_outcome: boolean;
// Also ask for prints Bambuddy archived but did not dispatch (#1898)
confirm_outcome_external_prints: boolean;
// Count unanswered outcome prompts as "good" when the plate is released (#1898)
confirm_default_good_on_plate_clear: boolean;
// Staggered batch start defaults
stagger_group_size: number;
stagger_interval_minutes: number;
@@ -2596,6 +2617,8 @@ export interface PrintQueueItem {
timelapse: boolean;
use_ams: boolean;
nozzle_offset_cali: CalibrationMode;
// Ask for a post-print outcome verdict when this job completes (#1898)
confirm_outcome: boolean;
preheat_override: 'inherit' | 'on' | 'off';
preheat_chamber_target_override: number | null;
status: 'pending' | 'printing' | 'completed' | 'failed' | 'skipped' | 'cancelled';
@@ -2726,6 +2749,8 @@ export interface PrintQueueItemCreate {
timelapse?: boolean;
use_ams?: boolean;
nozzle_offset_cali?: CalibrationMode;
// Ask for a post-print outcome verdict when this job completes (#1898)
confirm_outcome?: boolean;
preheat_override?: 'inherit' | 'on' | 'off';
preheat_chamber_target_override?: number | null;
// Auto-print G-code injection
@@ -2814,6 +2839,8 @@ export interface PrintQueueItemUpdate {
timelapse?: boolean;
use_ams?: boolean;
nozzle_offset_cali?: CalibrationMode;
// Ask for a post-print outcome verdict when this job completes (#1898)
confirm_outcome?: boolean;
preheat_override?: 'inherit' | 'on' | 'off';
preheat_chamber_target_override?: number | null;
// Auto-print G-code injection
@@ -2841,6 +2868,8 @@ export interface PrintQueueBulkUpdate {
timelapse?: boolean;
use_ams?: boolean;
nozzle_offset_cali?: CalibrationMode;
// Ask for a post-print outcome verdict when this job completes (#1898)
confirm_outcome?: boolean;
preheat_override?: 'inherit' | 'on' | 'off';
preheat_chamber_target_override?: number | null;
// Auto-print G-code injection
@@ -2981,6 +3010,8 @@ export interface NotificationProvider {
// Build plate detection
on_plate_not_empty: boolean;
on_plate_clear_required: boolean;
// Post-print outcome confirmation (#1898)
on_print_confirm_request: boolean;
// Bed cooled
on_bed_cooled: boolean;
on_ha_sensor_alert: boolean;
@@ -3045,6 +3076,8 @@ export interface NotificationProviderCreate {
// Build plate detection
on_plate_not_empty?: boolean;
on_plate_clear_required?: boolean;
// Post-print outcome confirmation (#1898)
on_print_confirm_request?: boolean;
// Bed cooled
on_bed_cooled?: boolean;
on_ha_sensor_alert?: boolean;
@@ -3102,6 +3135,8 @@ export interface NotificationProviderUpdate {
// Build plate detection
on_plate_not_empty?: boolean;
on_plate_clear_required?: boolean;
// Post-print outcome confirmation (#1898)
on_print_confirm_request?: boolean;
// Bed cooled
on_bed_cooled?: boolean;
on_ha_sensor_alert?: boolean;
@@ -5105,6 +5140,11 @@ export const api = {
quantity?: number;
external_url?: string | null;
filament_used_grams?: number | null;
// Post-print outcome verdict (#1898); null clears it
user_verdict?: 'good' | 'reject' | null;
// Which surface answered. The backend only accepts the sources a client
// can honestly claim and defaults to 'api' when none is given.
user_verdict_source?: 'dialog' | 'printer_card';
}) =>
request<Archive>(`/archives/${id}`, {
method: 'PATCH',