@@ -20,6 +20,7 @@ import {
2020 getOpportunityTitle ,
2121 OPPORTUNITY_DEPENDENCY_MAP ,
2222 getOpportunitiesForAudit ,
23+ computeAuditCompletion ,
2324} from '@adobe/spacecat-shared-utils' ;
2425import { getAuditStatus } from '../../utils/cloudwatch-utils.js' ;
2526import { checkAndAlertBotProtection } from '../../utils/bot-detection.js' ;
@@ -217,54 +218,6 @@ async function isScrapingAvailable(baseUrl, context, onboardStartTime) {
217218 }
218219}
219220
220- /**
221- * Checks which audit types have completed since onboardStartTime by querying the database.
222- * An audit is considered completed if a record exists with auditedAt >= onboardStartTime.
223- * Falls back conservatively (all pending) if the DB query fails.
224- *
225- * @param {string } siteId - The site ID
226- * @param {Array<string> } auditTypes - Audit types expected for this onboard session
227- * @param {number } onboardStartTime - Onboarding start timestamp in ms
228- * @param {object } dataAccess - Data access object
229- * @param {object } log - Logger
230- * @returns {Promise<{pendingAuditTypes: Array<string>, completedAuditTypes: Array<string>}> }
231- */
232- async function checkAuditCompletionFromDB ( siteId , auditTypes , onboardStartTime , dataAccess , log ) {
233- const pendingAuditTypes = [ ] ;
234- const completedAuditTypes = [ ] ;
235- try {
236- const { Audit } = dataAccess ;
237- const latestAudits = await Audit . allLatestForSite ( siteId ) ;
238- const auditsByType = { } ;
239- if ( latestAudits ) {
240- for ( const audit of latestAudits ) {
241- auditsByType [ audit . getAuditType ( ) ] = audit ;
242- }
243- }
244- for ( const auditType of auditTypes ) {
245- const audit = auditsByType [ auditType ] ;
246- if ( ! audit ) {
247- pendingAuditTypes . push ( auditType ) ;
248- } else {
249- const auditedAt = new Date ( audit . getAuditedAt ( ) ) . getTime ( ) ;
250- if ( Number . isNaN ( auditedAt ) || auditedAt < onboardStartTime ) {
251- // Unparseable timestamp or audit predates this onboard session — treat as pending
252- pendingAuditTypes . push ( auditType ) ;
253- } else {
254- completedAuditTypes . push ( auditType ) ;
255- }
256- }
257- }
258- } catch ( error ) {
259- log . warn ( `Could not check audit completion from DB for site ${ siteId } : ${ error . message } ` ) ;
260- // Conservative fallback: mark all as pending so disclaimer is always shown on error
261- // Reset first to avoid duplicates if some types were already pushed before the error
262- pendingAuditTypes . length = 0 ;
263- pendingAuditTypes . push ( ...auditTypes . filter ( ( t ) => ! completedAuditTypes . includes ( t ) ) ) ;
264- }
265- return { pendingAuditTypes, completedAuditTypes } ;
266- }
267-
268221/**
269222 * Analyzes missing opportunities and determines the root cause
270223 * @param {Array<string> } missingOpportunities - Array of missing opportunity types
@@ -582,8 +535,16 @@ export async function runOpportunityStatusProcessor(message, context) {
582535 // Only meaningful when we have an onboardStartTime anchor to compare against.
583536 let pendingAuditTypes = [ ] ;
584537 if ( auditTypes && auditTypes . length > 0 && onboardStartTime ) {
585- // eslint-disable-next-line max-len
586- ( { pendingAuditTypes } = await checkAuditCompletionFromDB ( siteId , auditTypes , onboardStartTime , dataAccess , log ) ) ;
538+ try {
539+ const { Audit } = dataAccess ;
540+ const latestAudits = await Audit . allLatestForSite ( siteId ) ;
541+ const completion = computeAuditCompletion ( auditTypes , onboardStartTime , latestAudits ) ;
542+ pendingAuditTypes = completion . pendingAuditTypes ;
543+ } catch ( auditErr ) {
544+ log . warn ( `Could not check audit completion from DB for site ${ siteId } : ${ auditErr . message } ` ) ;
545+ // Conservative fallback: mark all as pending so disclaimer is always shown on error
546+ pendingAuditTypes = [ ...auditTypes ] ;
547+ }
587548 }
588549
589550 // Process opportunities by type to avoid duplicates
0 commit comments