-- name: CreateBatchUpload :one INSERT INTO batch_uploads (client_id, original_filename, total_documents) VALUES ($1, $2, $3) RETURNING id; -- name: CreateBatchUploadWithStorage :one INSERT INTO batch_uploads ( client_id, original_filename, total_documents, status, archive_bucket, archive_key, file_size_bytes ) VALUES ($1, $2, $3, $4::batch_status, $5, $6, $7) RETURNING id, created_at; -- name: GetBatchUpload :one SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, progress_percent, failed_filenames, created_at, completed_at FROM batch_uploads WHERE id = $1 AND client_id = $2; -- name: GetBatchUploadWithStorage :one SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, archive_bucket, archive_key, file_size_bytes, failed_filenames, created_at, completed_at FROM batch_uploads WHERE id = $1 AND client_id = $2; -- name: ListBatchUploads :many SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, progress_percent, created_at, completed_at FROM batch_uploads WHERE client_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3; -- name: UpdateBatchProgress :exec UPDATE batch_uploads SET processed_documents = $2, failed_documents = $3, invalid_type_documents = $4, progress_percent = $5 WHERE id = $1; -- name: UpdateBatchStatus :exec UPDATE batch_uploads SET status = $2::batch_status, completed_at = CASE WHEN $2::batch_status IN ('completed', 'failed', 'cancelled') THEN NOW() ELSE NULL END WHERE id = $1; -- name: AddFailedFilename :exec UPDATE batch_uploads SET failed_filenames = failed_filenames || jsonb_build_array($2::text) WHERE id = $1; -- name: GetDocumentsByBatchId :many SELECT id, clientId, hash FROM documents WHERE batch_id = $1; -- name: CountDocumentsByBatchId :one SELECT COUNT(*) as count FROM documents WHERE batch_id = $1; -- name: GetUnprocessedBatches :many SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, progress_percent, created_at, completed_at FROM batch_uploads WHERE status = 'processing' ORDER BY created_at ASC; -- name: InsertBatchDocumentOutcome :exec -- Upsert: if a row for this (batch_id, filename) already exists (e.g. batch -- retry after partial failure), overwrite it with the latest outcome. INSERT INTO batch_document_outcomes (batch_id, filename, outcome, error_detail, document_id) VALUES ($1, $2, $3::batch_outcome_status, $4, $5) ON CONFLICT (batch_id, filename) DO UPDATE SET outcome = EXCLUDED.outcome, error_detail = EXCLUDED.error_detail, document_id = EXCLUDED.document_id, updated_at = NOW(); -- name: UpdateBatchDocumentOutcomeByDocumentID :exec -- Updates the outcome for a document progressing through the pipeline. -- Only updates rows in non-terminal pipeline states to prevent overwriting -- terminal outcomes (e.g. a 'duplicate' row from a different batch that -- shares the same document_id). UPDATE batch_document_outcomes SET outcome = $2::batch_outcome_status, error_detail = $3, updated_at = NOW() WHERE document_id = $1 AND outcome IN ('submitted', 'init_complete', 'sync_complete'); -- name: ResolveBatchDocumentOutcome :exec -- Called by docInitRunner to set the document_id on a previously-submitted -- outcome row and update the outcome to an init-stage result. -- Finds the row by batch_id + filename since document_id is NULL at this point. UPDATE batch_document_outcomes SET document_id = $3, outcome = $4::batch_outcome_status, error_detail = $5, updated_at = NOW() WHERE batch_id = $1 AND filename = $2 AND document_id IS NULL; -- name: ListBatchDocumentOutcomes :many -- Returns all outcome rows for a batch, with clean failure detail -- joined from currentCleanEntries when applicable. SELECT bdo.id, bdo.batch_id, bdo.filename, bdo.outcome, bdo.error_detail, bdo.document_id, bdo.created_at, bdo.updated_at, cce.fail as clean_fail FROM batch_document_outcomes bdo LEFT JOIN currentCleanEntries cce ON cce.documentId = bdo.document_id WHERE bdo.batch_id = $1 ORDER BY bdo.created_at ASC;