feat(expense): add persistent zero-entry receipt association
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
import * as aiAttachmentAssociationModel from '../../utils/aiAttachmentAssociationModel.js'
|
||||
import { fetchAttachmentAssociationJob } from '../../services/attachmentAssociationJobs.js'
|
||||
import {
|
||||
buildAttachmentAssociationCandidateActions,
|
||||
isAttachmentAssociationConfirmationResult,
|
||||
resolveAttachmentAssociationTarget
|
||||
} from '../../utils/attachmentAssociationJobModel.js'
|
||||
import {
|
||||
fetchAttachmentAssociationJob,
|
||||
normalizeAttachmentAssociationJob
|
||||
} from '../../services/attachmentAssociationJobs.js'
|
||||
|
||||
const ATTACHMENT_ASSOCIATION_JOB_POLL_INTERVAL_MS = 1200
|
||||
const ATTACHMENT_ASSOCIATION_JOB_MAX_POLLS = 90
|
||||
@@ -25,23 +33,7 @@ export function useWorkbenchAiAttachmentAssociationJobs({
|
||||
}
|
||||
|
||||
function normalizeJob(job = {}) {
|
||||
const jobId = String(job?.job_id || job?.jobId || '').trim()
|
||||
if (!jobId) {
|
||||
return null
|
||||
}
|
||||
return {
|
||||
jobId,
|
||||
status: String(job?.status || 'queued').trim() || 'queued',
|
||||
message: String(job?.message || '').trim(),
|
||||
receiptIds: (Array.isArray(job?.receipt_ids) ? job.receipt_ids : job?.receiptIds || [])
|
||||
.map((item) => String(item || '').trim())
|
||||
.filter(Boolean),
|
||||
claimId: String(job?.claim_id || job?.claimId || '').trim(),
|
||||
claimNo: String(job?.claim_no || job?.claimNo || '').trim(),
|
||||
uploadedCount: Number(job?.uploaded_count ?? job?.uploadedCount ?? 0) || 0,
|
||||
skippedCount: Number(job?.skipped_count ?? job?.skippedCount ?? 0) || 0,
|
||||
error: String(job?.error || '').trim()
|
||||
}
|
||||
return normalizeAttachmentAssociationJob(job)
|
||||
}
|
||||
|
||||
function isPending(job = {}) {
|
||||
@@ -112,12 +104,39 @@ export function useWorkbenchAiAttachmentAssociationJobs({
|
||||
if (!findMessage(messageId)) {
|
||||
return true
|
||||
}
|
||||
if (isAttachmentAssociationConfirmationResult(normalizedJob)) {
|
||||
const confirmationMessage = aiAttachmentAssociationModel.buildAiAttachmentAssociationConfirmationResultMessage({
|
||||
job: normalizedJob,
|
||||
fileNames
|
||||
})
|
||||
await streamOrSetInlineAssistantContent(messageId, confirmationMessage)
|
||||
replaceJobMessage(messageId, confirmationMessage, {
|
||||
attachmentAssociationJob: normalizedJob,
|
||||
attachmentOcrDetails,
|
||||
stewardPlan: {
|
||||
streamStatus: 'completed',
|
||||
thinkingEvents: buildThinkingEvents('completed')
|
||||
},
|
||||
suggestedActions: buildAttachmentAssociationCandidateActions(normalizedJob)
|
||||
})
|
||||
persistCurrentConversation()
|
||||
return true
|
||||
}
|
||||
if (normalizedJob.status === 'succeeded') {
|
||||
const target = resolveAttachmentAssociationTarget(normalizedJob)
|
||||
const finalMessageText = aiAttachmentAssociationModel.buildAiAttachmentAssociationResultMessage({
|
||||
claimNo: normalizedJob.claimNo,
|
||||
claimNo: target.claimNo,
|
||||
fileNames,
|
||||
uploadedCount: normalizedJob.uploadedCount,
|
||||
skippedCount: normalizedJob.skippedCount
|
||||
skippedCount: normalizedJob.skippedCount,
|
||||
applicationClaimNo: normalizedJob.applicationClaimNo,
|
||||
confidence: normalizedJob.confidence,
|
||||
matchReasons: normalizedJob.matchReasons,
|
||||
riskItems: normalizedJob.riskItems,
|
||||
confirmationRequired: Boolean(
|
||||
normalizedJob.draftPayload?.confirmationRequired
|
||||
?? normalizedJob.draftPayload?.confirmation_required
|
||||
)
|
||||
})
|
||||
await streamOrSetInlineAssistantContent(messageId, finalMessageText)
|
||||
replaceJobMessage(messageId, finalMessageText, {
|
||||
@@ -128,13 +147,13 @@ export function useWorkbenchAiAttachmentAssociationJobs({
|
||||
thinkingEvents: buildThinkingEvents('completed')
|
||||
},
|
||||
suggestedActions: buildDetailActions({
|
||||
claimId: normalizedJob.claimId,
|
||||
claimNo: normalizedJob.claimNo
|
||||
claimId: target.claimId,
|
||||
claimNo: target.claimNo
|
||||
})
|
||||
})
|
||||
notifyRequestUpdated?.({
|
||||
claimId: normalizedJob.claimId,
|
||||
claimNo: normalizedJob.claimNo,
|
||||
claimId: target.claimId,
|
||||
claimNo: target.claimNo,
|
||||
source: 'ai-workbench-attachment-association-job',
|
||||
uploadedCount: normalizedJob.uploadedCount,
|
||||
skippedCount: normalizedJob.skippedCount
|
||||
@@ -244,7 +263,7 @@ export function useWorkbenchAiAttachmentAssociationJobs({
|
||||
extractReceiptIdsFromOcrDocuments,
|
||||
normalizeJob,
|
||||
pollJob,
|
||||
resumePendingJobs
|
||||
resumePendingJobs,
|
||||
updateJobMessage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user