tango-app-api-trax 3.7.88 → 3.7.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -3489,215 +3489,216 @@ export const downloadInsertPdf = async ( req, res ) => {
|
|
|
3489
3489
|
const safeName = ( str ) =>
|
|
3490
3490
|
( str || '' ).toString().replace( /[<>:"/\\|?*]+/g, '_' );
|
|
3491
3491
|
for ( const checklistInfo of checklistInfoList ) {
|
|
3492
|
-
|
|
3493
|
-
if ( dayjs.utc().diff( dayjs.utc( checklistInfo.scheduleEndTime, 'hh:mm A' ), 'minute' ) == 30 ) {
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3492
|
+
console.log( dayjs.utc().diff( dayjs.utc( checklistInfo.scheduleEndTime, 'hh:mm A' ), 'minute' ) );
|
|
3493
|
+
// if ( dayjs.utc().diff( dayjs.utc( checklistInfo.scheduleEndTime, 'hh:mm A' ), 'minute' ) == 30 ) {
|
|
3494
|
+
let data = {
|
|
3495
|
+
checklistName: checklistInfo.checkListName,
|
|
3496
|
+
date: todayStr,
|
|
3497
|
+
total: checklistInfo?.storeCount,
|
|
3498
|
+
};
|
|
3499
|
+
const emailFileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/autoEmail.hbs', 'utf8' );
|
|
3500
|
+
const emailHtmlContent = handlebars.compile( emailFileContent );
|
|
3501
|
+
const emailHtml = emailHtmlContent( { data: data } );
|
|
3502
|
+
let emailList = [];
|
|
3503
|
+
|
|
3504
|
+
if ( checklistInfo?.autoEmail?.type?.includes( 'approver' ) ) {
|
|
3505
|
+
emailList = ( checklistInfo.approver || [] )
|
|
3506
|
+
.map( ( e ) => e?.value )
|
|
3507
|
+
.filter( Boolean );
|
|
3508
|
+
}
|
|
3509
3509
|
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3510
|
+
if ( Array.isArray( checklistInfo?.autoEmail?.users ) ) {
|
|
3511
|
+
emailList.push(
|
|
3512
|
+
...checklistInfo.autoEmail.users
|
|
3513
|
+
.map( ( e ) => e?.value )
|
|
3514
|
+
.filter( Boolean ),
|
|
3515
|
+
);
|
|
3516
|
+
}
|
|
3517
3517
|
|
|
3518
|
-
|
|
3518
|
+
if ( !emailList.length ) continue;
|
|
3519
3519
|
|
|
3520
|
-
|
|
3520
|
+
const brandInfo = await getBrandInfo( checklistInfo.client_id );
|
|
3521
3521
|
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3522
|
+
const submittedDetails = await processedchecklist.find( {
|
|
3523
|
+
sourceCheckList_id: checklistInfo._id,
|
|
3524
|
+
checklistStatus: 'submit',
|
|
3525
|
+
date_string: todayStr,
|
|
3526
|
+
} );
|
|
3527
3527
|
|
|
3528
|
-
|
|
3528
|
+
if ( !submittedDetails.length ) continue;
|
|
3529
3529
|
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3530
|
+
// console.log(
|
|
3531
|
+
// `Processing checklist: ${checklistInfo.checkListName} (${submittedDetails.length} records)`,
|
|
3532
|
+
// );
|
|
3533
3533
|
|
|
3534
|
-
|
|
3534
|
+
const ZIP_LIMIT = 100;
|
|
3535
3535
|
|
|
3536
|
-
|
|
3537
|
-
|
|
3536
|
+
for ( let i = 0; i < submittedDetails.length; i += ZIP_LIMIT ) {
|
|
3537
|
+
const batch = submittedDetails.slice( i, i + ZIP_LIMIT );
|
|
3538
3538
|
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3539
|
+
const zipName = `${safeName(
|
|
3540
|
+
checklistInfo.checkListName,
|
|
3541
|
+
)}_${todayStr}_part_${Math.floor( i / ZIP_LIMIT ) + 1}.zip`;
|
|
3542
3542
|
|
|
3543
|
-
|
|
3543
|
+
const zipPath = path.join( '/tmp', zipName );
|
|
3544
3544
|
|
|
3545
|
-
|
|
3546
|
-
|
|
3545
|
+
const output = fs.createWriteStream( zipPath );
|
|
3546
|
+
const archive = archiver( 'zip', { zlib: { level: 9 } } );
|
|
3547
3547
|
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3548
|
+
archive.on( 'error', ( err ) => {
|
|
3549
|
+
logger.error( { message: 'Archiver error', error: err } );
|
|
3550
|
+
// console.error( '❌ Archiver error:', err );
|
|
3551
|
+
throw err;
|
|
3552
|
+
} );
|
|
3553
3553
|
|
|
3554
|
-
|
|
3554
|
+
archive.pipe( output );
|
|
3555
3555
|
|
|
3556
|
-
|
|
3556
|
+
let appendedCount = 0;
|
|
3557
3557
|
|
|
3558
|
-
|
|
3559
|
-
|
|
3558
|
+
for ( const checklistDetails of batch ) {
|
|
3559
|
+
const doc =
|
|
3560
3560
|
typeof checklistDetails.toObject === 'function' ?
|
|
3561
3561
|
checklistDetails.toObject() :
|
|
3562
3562
|
{ ...checklistDetails };
|
|
3563
3563
|
|
|
3564
3564
|
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3565
|
+
const detectionPayload = {
|
|
3566
|
+
'storeId': [ doc.store_id ],
|
|
3567
|
+
'userEmail': doc.userEmail,
|
|
3568
|
+
'sourceChecklist_id': doc.sourceCheckList_id,
|
|
3569
|
+
};
|
|
3570
3570
|
|
|
3571
3571
|
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3572
|
+
// let complianceURL = JSON.parse( process.env.LAMBDAURL ).complianceHistory;
|
|
3573
|
+
let complianceURL = 'https://pbxdm4nstcpbaz6gf6c53ofeee0zvmfy.lambda-url.ap-south-1.on.aws/';
|
|
3574
|
+
const complianceData = await LamdaServiceCall( complianceURL, detectionPayload );
|
|
3575
|
+
if ( complianceData?.data.length ) {
|
|
3576
|
+
doc['historyData'] = complianceData.data;
|
|
3577
|
+
}
|
|
3578
|
+
// CDN fix
|
|
3579
|
+
( doc.questionAnswers || [] ).forEach( ( section ) => {
|
|
3580
|
+
( section.questions || [] ).forEach( ( question ) => {
|
|
3581
|
+
( question.userAnswer || [] ).forEach( ( answer ) => {
|
|
3582
|
+
if ( answer?.referenceImage?.trim() ) {
|
|
3583
|
+
answer.referenceImage =
|
|
3583
3584
|
cdnBase + answer.referenceImage;
|
|
3584
|
-
|
|
3585
|
-
} );
|
|
3585
|
+
}
|
|
3586
3586
|
} );
|
|
3587
3587
|
} );
|
|
3588
|
+
} );
|
|
3588
3589
|
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3590
|
+
const templateData = buildVisitChecklistTemplateData(
|
|
3591
|
+
doc,
|
|
3592
|
+
brandInfo,
|
|
3593
|
+
);
|
|
3593
3594
|
|
|
3594
|
-
|
|
3595
|
-
|
|
3595
|
+
const resolvedData = resolveTemplateUrls( templateData, cdnBase );
|
|
3596
|
+
await imageCache.resolveAllImages( resolvedData );
|
|
3596
3597
|
|
|
3597
|
-
|
|
3598
|
+
const html = pdfTemplate( resolvedData );
|
|
3598
3599
|
|
|
3599
|
-
|
|
3600
|
+
// console.log( 'HTML length:', html?.length );
|
|
3600
3601
|
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3602
|
+
if ( !html || html.length < 50 ) {
|
|
3603
|
+
logger.error( { functionName: 'Invalid HTML skipped:', error: doc._id } );
|
|
3604
|
+
// console.error( '❌ Invalid HTML skipped:', doc._id );
|
|
3605
|
+
continue;
|
|
3606
|
+
}
|
|
3606
3607
|
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3608
|
+
try {
|
|
3609
|
+
await page.setContent( html, {
|
|
3610
|
+
waitUntil: 'domcontentloaded',
|
|
3611
|
+
timeout: 0,
|
|
3612
|
+
} );
|
|
3612
3613
|
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3614
|
+
await new Promise( ( r ) => setTimeout( r, 300 ) );
|
|
3615
|
+
await page.emulateMediaType( 'screen' );
|
|
3616
|
+
} catch ( err ) {
|
|
3617
|
+
logger.error( { functionName: 'setContent failed:', error: err } );
|
|
3618
|
+
// console.error( '❌ setContent failed:', err );
|
|
3619
|
+
continue;
|
|
3620
|
+
}
|
|
3620
3621
|
|
|
3621
|
-
|
|
3622
|
+
let pdfBuffer;
|
|
3622
3623
|
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3624
|
+
try {
|
|
3625
|
+
pdfBuffer = await page.pdf( {
|
|
3626
|
+
format: 'A4',
|
|
3627
|
+
printBackground: true,
|
|
3628
|
+
margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
|
|
3629
|
+
} );
|
|
3629
3630
|
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3631
|
+
// console.log( 'PDF size:', pdfBuffer?.length );
|
|
3632
|
+
// console.log(
|
|
3633
|
+
// 'IsBuffer:',
|
|
3634
|
+
// Buffer.isBuffer( pdfBuffer ),
|
|
3635
|
+
// 'Type:',
|
|
3636
|
+
// pdfBuffer?.constructor?.name,
|
|
3637
|
+
// );
|
|
3638
|
+
} catch ( err ) {
|
|
3639
|
+
logger.error( { functionName: 'downloadInsertPdf', message: 'PDF generation failed', error: err } );
|
|
3640
|
+
continue;
|
|
3641
|
+
}
|
|
3641
3642
|
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3643
|
+
if ( !pdfBuffer || pdfBuffer.length === 0 ) {
|
|
3644
|
+
logger.error( { functionName: 'downloadInsertPdf', message: 'Empty PDF skipped', docId: doc._id } );
|
|
3645
|
+
continue;
|
|
3646
|
+
}
|
|
3646
3647
|
|
|
3647
|
-
|
|
3648
|
+
const finalBuffer = Buffer.isBuffer( pdfBuffer ) ?
|
|
3648
3649
|
pdfBuffer :
|
|
3649
3650
|
Buffer.from( pdfBuffer );
|
|
3650
3651
|
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3652
|
+
const pdfName = `${safeName(
|
|
3653
|
+
doc.storeName || doc.store_id || doc._id || 'store',
|
|
3654
|
+
)}.pdf`;
|
|
3654
3655
|
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3656
|
+
archive.append( finalBuffer, { name: pdfName } );
|
|
3657
|
+
appendedCount++;
|
|
3658
|
+
}
|
|
3658
3659
|
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3660
|
+
if ( appendedCount === 0 ) {
|
|
3661
|
+
logger.error( { functionName: 'No PDFs generated for batch, skipping ZIP', error: zipName } );
|
|
3662
|
+
// console.error( `❌ No PDFs generated for batch, skipping ZIP: ${zipName}` );
|
|
3663
|
+
archive.abort();
|
|
3664
|
+
output.destroy();
|
|
3665
|
+
continue;
|
|
3666
|
+
}
|
|
3666
3667
|
|
|
3667
|
-
|
|
3668
|
+
// console.log( `📄 ${appendedCount} PDFs added to ${zipName}` );
|
|
3668
3669
|
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3670
|
+
await new Promise( ( resolve, reject ) => {
|
|
3671
|
+
output.on( 'close', resolve );
|
|
3672
|
+
output.on( 'error', reject );
|
|
3673
|
+
archive.on( 'error', reject );
|
|
3673
3674
|
|
|
3674
|
-
|
|
3675
|
-
|
|
3675
|
+
archive.finalize();
|
|
3676
|
+
} );
|
|
3676
3677
|
|
|
3677
|
-
|
|
3678
|
-
|
|
3678
|
+
const zipBuffer = fs.readFileSync( zipPath );
|
|
3679
|
+
// console.log( `✅ ZIP ready: ${zipName}, archive pointer: ${archive.pointer()} bytes, file size: ${zipBuffer.length} bytes` );
|
|
3679
3680
|
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3681
|
+
const attachment = {
|
|
3682
|
+
filename: zipName,
|
|
3683
|
+
content: zipBuffer,
|
|
3684
|
+
contentType: 'application/zip',
|
|
3685
|
+
};
|
|
3685
3686
|
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
),
|
|
3687
|
+
await Promise.all(
|
|
3688
|
+
emailList.map( ( email ) =>
|
|
3689
|
+
sendEmailWithSES(
|
|
3690
|
+
email,
|
|
3691
|
+
'Checklist Report',
|
|
3692
|
+
emailHtml,
|
|
3693
|
+
attachment,
|
|
3694
|
+
sourceEmail,
|
|
3695
3695
|
),
|
|
3696
|
-
|
|
3696
|
+
),
|
|
3697
|
+
);
|
|
3697
3698
|
|
|
3698
|
-
|
|
3699
|
-
}
|
|
3699
|
+
// console.log( `📧 Emails sent for ${zipName}` );
|
|
3700
3700
|
}
|
|
3701
|
+
// }
|
|
3701
3702
|
}
|
|
3702
3703
|
} finally {
|
|
3703
3704
|
await browser.close();
|