tango-app-api-trax 3.7.89 → 3.7.91
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
|
@@ -18,7 +18,7 @@ import timeZone from 'dayjs/plugin/timezone.js';
|
|
|
18
18
|
import utc from 'dayjs/plugin/utc.js';
|
|
19
19
|
import { logger } from 'tango-app-api-middleware';
|
|
20
20
|
import mongoose from 'mongoose';
|
|
21
|
-
import { sendPushNotification, sendAiPushNotification, sendEmailWithSES, signedUrl } from 'tango-app-api-middleware';
|
|
21
|
+
import { sendPushNotification, sendAiPushNotification, sendEmailWithSES, signedUrl, fileUpload } from 'tango-app-api-middleware';
|
|
22
22
|
// import * as planoService from '../services/planogram.service.js';
|
|
23
23
|
import * as clusterServices from '../services/cluster.service.js';
|
|
24
24
|
import * as teamsServices from '../services/teams.service.js';
|
|
@@ -3489,214 +3489,230 @@ 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
|
-
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
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3518
|
-
if ( !emailList.length ) continue;
|
|
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 emailList = [];
|
|
3495
|
+
|
|
3496
|
+
if ( checklistInfo?.autoEmail?.type?.includes( 'approver' ) ) {
|
|
3497
|
+
emailList = ( checklistInfo.approver || [] )
|
|
3498
|
+
.map( ( e ) => e?.value )
|
|
3499
|
+
.filter( Boolean );
|
|
3500
|
+
}
|
|
3519
3501
|
|
|
3520
|
-
|
|
3502
|
+
if ( Array.isArray( checklistInfo?.autoEmail?.users ) ) {
|
|
3503
|
+
emailList.push(
|
|
3504
|
+
...checklistInfo.autoEmail.users
|
|
3505
|
+
.map( ( e ) => e?.value )
|
|
3506
|
+
.filter( Boolean ),
|
|
3507
|
+
);
|
|
3508
|
+
}
|
|
3521
3509
|
|
|
3522
|
-
|
|
3523
|
-
sourceCheckList_id: checklistInfo._id,
|
|
3524
|
-
checklistStatus: 'submit',
|
|
3525
|
-
date_string: todayStr,
|
|
3526
|
-
} );
|
|
3510
|
+
if ( !emailList.length ) continue;
|
|
3527
3511
|
|
|
3528
|
-
|
|
3512
|
+
const brandInfo = await getBrandInfo( checklistInfo.client_id );
|
|
3529
3513
|
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3514
|
+
const submittedDetails = await processedchecklist.find( {
|
|
3515
|
+
sourceCheckList_id: checklistInfo._id,
|
|
3516
|
+
checklistStatus: 'submit',
|
|
3517
|
+
date_string: todayStr,
|
|
3518
|
+
} );
|
|
3533
3519
|
|
|
3534
|
-
|
|
3520
|
+
if ( !submittedDetails.length ) continue;
|
|
3535
3521
|
|
|
3536
|
-
|
|
3537
|
-
|
|
3522
|
+
// console.log(
|
|
3523
|
+
// `Processing checklist: ${checklistInfo.checkListName} (${submittedDetails.length} records)`,
|
|
3524
|
+
// );
|
|
3538
3525
|
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
)}_${todayStr}_part_${Math.floor( i / ZIP_LIMIT ) + 1}.zip`;
|
|
3526
|
+
const ZIP_LIMIT = 100;
|
|
3527
|
+
let appendedCount = 0;
|
|
3542
3528
|
|
|
3543
|
-
|
|
3529
|
+
const zipName = `${safeName(
|
|
3530
|
+
checklistInfo.checkListName,
|
|
3531
|
+
)}_${todayStr}.zip`;
|
|
3544
3532
|
|
|
3545
|
-
|
|
3546
|
-
|
|
3533
|
+
const zipPath = path.join( '/tmp', zipName );
|
|
3534
|
+
const output = fs.createWriteStream( zipPath );
|
|
3535
|
+
const archive = archiver( 'zip', { zlib: { level: 9 } } );
|
|
3547
3536
|
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
} );
|
|
3537
|
+
archive.on( 'error', ( err ) => {
|
|
3538
|
+
logger.error( { message: 'Archiver error', error: err } );
|
|
3539
|
+
throw err;
|
|
3540
|
+
} );
|
|
3553
3541
|
|
|
3554
|
-
|
|
3542
|
+
archive.pipe( output );
|
|
3555
3543
|
|
|
3556
|
-
|
|
3544
|
+
for ( let i = 0; i < submittedDetails.length; i += ZIP_LIMIT ) {
|
|
3545
|
+
const batch = submittedDetails.slice( i, i + ZIP_LIMIT );
|
|
3557
3546
|
|
|
3558
|
-
|
|
3559
|
-
|
|
3547
|
+
for ( const checklistDetails of batch ) {
|
|
3548
|
+
const doc =
|
|
3560
3549
|
typeof checklistDetails.toObject === 'function' ?
|
|
3561
3550
|
checklistDetails.toObject() :
|
|
3562
3551
|
{ ...checklistDetails };
|
|
3563
3552
|
|
|
3564
3553
|
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3554
|
+
const detectionPayload = {
|
|
3555
|
+
'storeId': [ doc.store_id ],
|
|
3556
|
+
'userEmail': doc.userEmail,
|
|
3557
|
+
'sourceChecklist_id': doc.sourceCheckList_id,
|
|
3558
|
+
};
|
|
3570
3559
|
|
|
3571
3560
|
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3561
|
+
// let complianceURL = JSON.parse( process.env.LAMBDAURL ).complianceHistory;
|
|
3562
|
+
let complianceURL = 'https://pbxdm4nstcpbaz6gf6c53ofeee0zvmfy.lambda-url.ap-south-1.on.aws/';
|
|
3563
|
+
const complianceData = await LamdaServiceCall( complianceURL, detectionPayload );
|
|
3564
|
+
if ( complianceData?.data.length ) {
|
|
3565
|
+
doc['historyData'] = complianceData.data;
|
|
3566
|
+
}
|
|
3567
|
+
// CDN fix
|
|
3568
|
+
( doc.questionAnswers || [] ).forEach( ( section ) => {
|
|
3569
|
+
( section.questions || [] ).forEach( ( question ) => {
|
|
3570
|
+
( question.userAnswer || [] ).forEach( ( answer ) => {
|
|
3571
|
+
if ( answer?.referenceImage?.trim() ) {
|
|
3572
|
+
answer.referenceImage =
|
|
3583
3573
|
cdnBase + answer.referenceImage;
|
|
3584
|
-
|
|
3585
|
-
} );
|
|
3574
|
+
}
|
|
3586
3575
|
} );
|
|
3587
3576
|
} );
|
|
3577
|
+
} );
|
|
3588
3578
|
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3579
|
+
const templateData = buildVisitChecklistTemplateData(
|
|
3580
|
+
doc,
|
|
3581
|
+
brandInfo,
|
|
3582
|
+
);
|
|
3593
3583
|
|
|
3594
|
-
|
|
3595
|
-
|
|
3584
|
+
const resolvedData = resolveTemplateUrls( templateData, cdnBase );
|
|
3585
|
+
await imageCache.resolveAllImages( resolvedData );
|
|
3596
3586
|
|
|
3597
|
-
|
|
3587
|
+
const html = pdfTemplate( resolvedData );
|
|
3598
3588
|
|
|
3599
|
-
|
|
3589
|
+
// console.log( 'HTML length:', html?.length );
|
|
3600
3590
|
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3591
|
+
if ( !html || html.length < 50 ) {
|
|
3592
|
+
logger.error( { functionName: 'Invalid HTML skipped:', error: doc._id } );
|
|
3593
|
+
// console.error( '❌ Invalid HTML skipped:', doc._id );
|
|
3594
|
+
continue;
|
|
3595
|
+
}
|
|
3606
3596
|
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3597
|
+
try {
|
|
3598
|
+
await page.setContent( html, {
|
|
3599
|
+
waitUntil: 'domcontentloaded',
|
|
3600
|
+
timeout: 0,
|
|
3601
|
+
} );
|
|
3612
3602
|
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3603
|
+
await new Promise( ( r ) => setTimeout( r, 300 ) );
|
|
3604
|
+
await page.emulateMediaType( 'screen' );
|
|
3605
|
+
} catch ( err ) {
|
|
3606
|
+
logger.error( { functionName: 'setContent failed:', error: err } );
|
|
3607
|
+
// console.error( '❌ setContent failed:', err );
|
|
3608
|
+
continue;
|
|
3609
|
+
}
|
|
3620
3610
|
|
|
3621
|
-
|
|
3611
|
+
let pdfBuffer;
|
|
3622
3612
|
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3613
|
+
try {
|
|
3614
|
+
pdfBuffer = await page.pdf( {
|
|
3615
|
+
format: 'A4',
|
|
3616
|
+
printBackground: true,
|
|
3617
|
+
margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
|
|
3618
|
+
} );
|
|
3629
3619
|
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3620
|
+
// console.log( 'PDF size:', pdfBuffer?.length );
|
|
3621
|
+
// console.log(
|
|
3622
|
+
// 'IsBuffer:',
|
|
3623
|
+
// Buffer.isBuffer( pdfBuffer ),
|
|
3624
|
+
// 'Type:',
|
|
3625
|
+
// pdfBuffer?.constructor?.name,
|
|
3626
|
+
// );
|
|
3627
|
+
} catch ( err ) {
|
|
3628
|
+
logger.error( { functionName: 'downloadInsertPdf', message: 'PDF generation failed', error: err } );
|
|
3629
|
+
continue;
|
|
3630
|
+
}
|
|
3641
3631
|
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3632
|
+
if ( !pdfBuffer || pdfBuffer.length === 0 ) {
|
|
3633
|
+
logger.error( { functionName: 'downloadInsertPdf', message: 'Empty PDF skipped', docId: doc._id } );
|
|
3634
|
+
continue;
|
|
3635
|
+
}
|
|
3646
3636
|
|
|
3647
|
-
|
|
3637
|
+
const finalBuffer = Buffer.isBuffer( pdfBuffer ) ?
|
|
3648
3638
|
pdfBuffer :
|
|
3649
3639
|
Buffer.from( pdfBuffer );
|
|
3650
3640
|
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3641
|
+
const pdfName = `${safeName(
|
|
3642
|
+
doc.storeName || doc.store_id || doc._id || 'store',
|
|
3643
|
+
)}.pdf`;
|
|
3654
3644
|
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3645
|
+
archive.append( finalBuffer, { name: pdfName } );
|
|
3646
|
+
appendedCount++;
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
if ( appendedCount === 0 ) {
|
|
3650
|
+
logger.error( { functionName: 'No PDFs generated for batch, skipping ZIP', error: zipName } );
|
|
3651
|
+
// console.error( `❌ No PDFs generated for batch, skipping ZIP: ${zipName}` );
|
|
3652
|
+
archive.abort();
|
|
3653
|
+
output.destroy();
|
|
3654
|
+
continue;
|
|
3655
|
+
}
|
|
3658
3656
|
|
|
3659
|
-
|
|
3660
|
-
logger.error( { functionName: 'No PDFs generated for batch, skipping ZIP', error: zipName } );
|
|
3661
|
-
// console.error( `❌ No PDFs generated for batch, skipping ZIP: ${zipName}` );
|
|
3662
|
-
archive.abort();
|
|
3663
|
-
output.destroy();
|
|
3664
|
-
continue;
|
|
3665
|
-
}
|
|
3657
|
+
logger.info( { functionName: 'downloadInsertPdf', message: `${appendedCount} PDFs added to ${zipName}` } );
|
|
3666
3658
|
|
|
3667
|
-
|
|
3659
|
+
await new Promise( ( resolve, reject ) => {
|
|
3660
|
+
output.on( 'close', resolve );
|
|
3661
|
+
output.on( 'error', reject );
|
|
3662
|
+
archive.on( 'error', reject );
|
|
3668
3663
|
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
output.on( 'error', reject );
|
|
3672
|
-
archive.on( 'error', reject );
|
|
3664
|
+
archive.finalize();
|
|
3665
|
+
} );
|
|
3673
3666
|
|
|
3674
|
-
|
|
3675
|
-
|
|
3667
|
+
const zipBuffer = fs.readFileSync( zipPath );
|
|
3668
|
+
// console.log( `✅ ZIP ready: ${zipName}, archive pointer: ${archive.pointer()} bytes, file size: ${zipBuffer.length} bytes` );
|
|
3676
3669
|
|
|
3677
|
-
|
|
3678
|
-
|
|
3670
|
+
// const attachment = {
|
|
3671
|
+
// filename: zipName,
|
|
3672
|
+
// content: zipBuffer,
|
|
3673
|
+
// contentType: 'application/zip',
|
|
3674
|
+
// };
|
|
3679
3675
|
|
|
3680
|
-
|
|
3681
|
-
filename: zipName,
|
|
3682
|
-
content: zipBuffer,
|
|
3683
|
-
contentType: 'application/zip',
|
|
3684
|
-
};
|
|
3676
|
+
let bucket = JSON.parse( process.env.BUCKET );
|
|
3685
3677
|
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
sourceEmail,
|
|
3694
|
-
),
|
|
3695
|
-
),
|
|
3696
|
-
);
|
|
3678
|
+
let params = {
|
|
3679
|
+
fileName: zipName,
|
|
3680
|
+
Key: 'reports/',
|
|
3681
|
+
Bucket: bucket.sop,
|
|
3682
|
+
body: zipBuffer,
|
|
3683
|
+
ContentType: 'application/zip',
|
|
3684
|
+
};
|
|
3697
3685
|
|
|
3698
|
-
|
|
3699
|
-
|
|
3686
|
+
let zipURL = await fileUpload( params );
|
|
3687
|
+
|
|
3688
|
+
zipURL = await signedUrl( { file_path: zipURL.Key, Bucket: bucket.sop } );
|
|
3689
|
+
|
|
3690
|
+
let data = {
|
|
3691
|
+
checklistName: checklistInfo.checkListName,
|
|
3692
|
+
date: dayjs( todayStr, 'YYYY-MM-DD' ).format( 'DD-MM-YYYY' ),
|
|
3693
|
+
total: submittedDetails.length,
|
|
3694
|
+
zipURL: zipURL,
|
|
3695
|
+
};
|
|
3696
|
+
const emailFileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/autoEmail.hbs', 'utf8' );
|
|
3697
|
+
const emailHtmlContent = handlebars.compile( emailFileContent );
|
|
3698
|
+
const emailHtml = emailHtmlContent( { data: data } );
|
|
3699
|
+
|
|
3700
|
+
await Promise.all(
|
|
3701
|
+
emailList.map( ( email ) =>
|
|
3702
|
+
sendEmailWithSES(
|
|
3703
|
+
email,
|
|
3704
|
+
'Checklist Report',
|
|
3705
|
+
emailHtml,
|
|
3706
|
+
'',
|
|
3707
|
+
sourceEmail,
|
|
3708
|
+
),
|
|
3709
|
+
),
|
|
3710
|
+
);
|
|
3711
|
+
|
|
3712
|
+
try {
|
|
3713
|
+
fs.unlinkSync( zipPath );
|
|
3714
|
+
} catch ( cleanupErr ) {
|
|
3715
|
+
logger.error( { functionName: 'downloadInsertPdf', message: 'Failed to cleanup tmp file', error: cleanupErr } );
|
|
3700
3716
|
}
|
|
3701
3717
|
}
|
|
3702
3718
|
} finally {
|
package/src/hbs/autoEmail.hbs
CHANGED
|
@@ -1,216 +1,235 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
|
|
6
|
-
<meta charset="utf-8">
|
|
7
|
-
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
8
|
-
<title>Trial Intiate Email</title>
|
|
9
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10
|
-
<style type="text/css">
|
|
11
|
-
@media screen {
|
|
12
|
-
@font-face {
|
|
13
|
-
font-family: 'Inter';
|
|
14
|
-
font-style: normal;
|
|
15
|
-
font-weight: 400;
|
|
16
|
-
font-display: swap;
|
|
17
|
-
src: local("Inter"), local("Inter-Regular"), url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZJhiI2B.woff2) format('woff2');
|
|
18
|
-
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
body {
|
|
23
|
-
font-family: "Inter", sans-serif !important;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
body,
|
|
27
|
-
table,
|
|
28
|
-
td,
|
|
29
|
-
a {
|
|
30
|
-
-ms-text-size-adjust: 100%;
|
|
31
|
-
-webkit-text-size-adjust: 100%;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
table,
|
|
35
|
-
td {
|
|
36
|
-
mso-table-rspace: 0pt;
|
|
37
|
-
mso-table-lspace: 0pt;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
img {
|
|
41
|
-
-ms-interpolation-mode: bicubic;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
a[x-apple-data-detectors] {
|
|
45
|
-
font-family: "inherit" !important;
|
|
46
|
-
font-size: inherit !important;
|
|
47
|
-
font-weight: inherit !important;
|
|
48
|
-
line-height: inherit !important;
|
|
49
|
-
color: inherit !important;
|
|
50
|
-
text-decoration: none !important;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
div[style*="margin: 16px 0;"
|
|
55
|
-
|
|
56
|
-
] {
|
|
57
|
-
margin: 0 !important;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
body {
|
|
61
|
-
width: 100% !important;
|
|
62
|
-
height: 100% !important;
|
|
63
|
-
padding: 0 !important;
|
|
64
|
-
margin: 0 !important;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
table {
|
|
69
|
-
border-collapse: collapse !important;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
a {
|
|
73
|
-
color: #1a82e2;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
img {
|
|
77
|
-
height: auto;
|
|
78
|
-
line-height: 100%;
|
|
79
|
-
text-decoration: none;
|
|
80
|
-
border: 0;
|
|
81
|
-
outline: none;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.flagText {
|
|
85
|
-
/* font-family: 'Inter'; */
|
|
86
|
-
/* color: #667085 !important; */
|
|
87
|
-
font-size: 16px;
|
|
88
|
-
font-weight: 600;
|
|
89
|
-
line-height: 24px;
|
|
90
|
-
text-align: left;
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
</style>
|
|
94
|
-
|
|
95
|
-
</head>
|
|
96
|
-
|
|
97
|
-
<body style="background-color: #dbe5ea;">
|
|
98
|
-
|
|
99
|
-
<div class="preheader"
|
|
100
|
-
style="display: none; max-width: 0; max-height: 0; overflow: hidden; font-size: 1px; line-height: 1px; color: #fff; opacity: 0;">
|
|
101
|
-
Email Summary (Hidden)
|
|
102
|
-
</div>
|
|
103
|
-
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="padding-left:10px;padding-right:10px">
|
|
104
|
-
<tr>
|
|
105
|
-
<td bgcolor="#dbe5ea" style="padding:32px 10px 0 10px">
|
|
106
|
-
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 680px;" align="center">
|
|
107
|
-
<tr>
|
|
108
|
-
<td class="o_bg-white o_px-md o_py-md o_sans o_text"
|
|
109
|
-
style="margin-top: 0px;margin-bottom: 0px;font-size: 16px;line-height: 24px;background-color: #ffffff;padding-left: 18px;padding-right: 24px;padding-top: 24px;padding-bottom: 24px;">
|
|
110
|
-
<p style="margin-top: 0px;margin-bottom: 0px;"><a class="o_text-white"
|
|
111
|
-
href="https://tangoeye.ai/"
|
|
112
|
-
style="text-decoration: none;outline: none;color: #ffffff;"><img
|
|
113
|
-
src="https://devtangoretail-api.tangoeye.ai/logo.png" width="200" height="100"
|
|
114
|
-
alt="SimpleApp"
|
|
115
|
-
style="-ms-interpolation-mode: bicubic;vertical-align: middle;border: 0;line-height: 100%;height: auto;outline: none;text-decoration: none;"></a>
|
|
116
|
-
</p>
|
|
117
|
-
</td>
|
|
118
|
-
</tr>
|
|
119
|
-
<tr>
|
|
120
|
-
<td align="left" bgcolor="#ffffff"
|
|
121
|
-
style="padding-left: 30px;padding-right: 24px; font-size: 14px; line-height: 24px;">
|
|
122
|
-
<p class="o_heading o_mb-xxs"
|
|
123
|
-
style="width: 624px;height: 0px;border: 1px solid #CBD5E1;flex: none;order: 1;flex-grow: 0;">
|
|
124
|
-
</p>
|
|
125
|
-
</td>
|
|
126
|
-
</tr>
|
|
127
|
-
<tr>
|
|
128
|
-
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
129
|
-
style="background-color: #ffffff;padding-left: 30px;padding-right: 24px;padding-bottom: 10px;">
|
|
130
|
-
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
131
|
-
style="margin-top: 0px;margin-bottom: 0px;font-size: 16px;line-height: 28px;color: #82899a;">
|
|
132
|
-
<span class="o_heading o_text-dark o_mb-xxs"
|
|
133
|
-
style="font-weight: 400;margin-top: 0px;margin-bottom: 4px;color: #121A26;line-height: 140%;">
|
|
134
|
-
Hi,<br />
|
|
135
|
-
Store compliance summary has been generated for a recently completed checklist across multiple stores. Review the
|
|
136
|
-
compliance performance and identify stores that require attention from the dashboard.
|
|
137
|
-
</span>
|
|
138
|
-
</div>
|
|
139
|
-
</td>
|
|
140
|
-
</tr>
|
|
141
|
-
<tr>
|
|
142
|
-
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
143
|
-
style="background-color: #ffffff;padding-left: 30px;padding-right: 24px;padding-bottom: 10px;">
|
|
144
|
-
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
145
|
-
style="margin-top: 0px;margin-bottom: 0px;font-size: 16px;line-height: 28px;color: #82899a;">
|
|
146
|
-
<span class="o_heading o_text-dark o_mb-xxs"
|
|
147
|
-
style="font-weight: 400;margin-top: 0px;margin-bottom: 4px;color: #121A26;line-height: 140%;">
|
|
148
|
-
Details of the checklist are as follows:
|
|
149
|
-
</span>
|
|
150
|
-
</div>
|
|
151
|
-
</td>
|
|
152
|
-
</tr>
|
|
153
|
-
</table>
|
|
154
|
-
</td>
|
|
155
|
-
</tr>
|
|
156
|
-
<tr>
|
|
157
|
-
<td align="center" bgcolor="#dbe5ea" style="padding:0 10px 0 10px">
|
|
158
|
-
<table align="center" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="0" width="100%"
|
|
159
|
-
style="max-width: 680px;">
|
|
160
|
-
<tr bgcolor="#ffffff" style="border:none;margin-top:0px;">
|
|
161
|
-
<td class="flagText" style="padding-left:30px; line-height: 24px;color:#000000">Checklist Name:
|
|
162
|
-
</td>
|
|
163
|
-
<td></td>
|
|
164
|
-
<td></td>
|
|
165
|
-
<td class="flagText">{{data.checklistName}}</td>
|
|
166
|
-
</tr>
|
|
167
|
-
<tr bgcolor="#ffffff" style="border:none;margin-top:3px;">
|
|
168
|
-
<td class="flagText" style="padding-left:30px; line-height: 24px;">Total Stores :</td>
|
|
169
|
-
<td></td>
|
|
170
|
-
<td></td>
|
|
171
|
-
<td class="flagText">{{data.total}}</td>
|
|
172
|
-
</tr>
|
|
173
|
-
|
|
174
|
-
<tr bgcolor="#ffffff" style="border:none;margin-top:3px;">
|
|
175
|
-
<td class="flagText" style="padding-left:30px; line-height: 24px;">Date :</td>
|
|
176
|
-
<td></td>
|
|
177
|
-
<td></td>
|
|
178
|
-
<td class="flagText">{{data.date}}</td>
|
|
179
|
-
</tr>
|
|
180
|
-
</table>
|
|
181
|
-
</td>
|
|
182
|
-
</tr>
|
|
183
|
-
<tr>
|
|
184
|
-
<td align="center" bgcolor="#dbe5ea" style="padding:0 10px
|
|
185
|
-
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 680px;">
|
|
186
|
-
<tr>
|
|
187
|
-
<td
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
</
|
|
215
|
-
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
|
|
6
|
+
<meta charset="utf-8">
|
|
7
|
+
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
8
|
+
<title>Trial Intiate Email</title>
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10
|
+
<style type="text/css">
|
|
11
|
+
@media screen {
|
|
12
|
+
@font-face {
|
|
13
|
+
font-family: 'Inter';
|
|
14
|
+
font-style: normal;
|
|
15
|
+
font-weight: 400;
|
|
16
|
+
font-display: swap;
|
|
17
|
+
src: local("Inter"), local("Inter-Regular"), url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZJhiI2B.woff2) format('woff2');
|
|
18
|
+
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
body {
|
|
23
|
+
font-family: "Inter", sans-serif !important;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
body,
|
|
27
|
+
table,
|
|
28
|
+
td,
|
|
29
|
+
a {
|
|
30
|
+
-ms-text-size-adjust: 100%;
|
|
31
|
+
-webkit-text-size-adjust: 100%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
table,
|
|
35
|
+
td {
|
|
36
|
+
mso-table-rspace: 0pt;
|
|
37
|
+
mso-table-lspace: 0pt;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
img {
|
|
41
|
+
-ms-interpolation-mode: bicubic;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
a[x-apple-data-detectors] {
|
|
45
|
+
font-family: "inherit" !important;
|
|
46
|
+
font-size: inherit !important;
|
|
47
|
+
font-weight: inherit !important;
|
|
48
|
+
line-height: inherit !important;
|
|
49
|
+
color: inherit !important;
|
|
50
|
+
text-decoration: none !important;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
div[style*="margin: 16px 0;"
|
|
55
|
+
|
|
56
|
+
] {
|
|
57
|
+
margin: 0 !important;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
body {
|
|
61
|
+
width: 100% !important;
|
|
62
|
+
height: 100% !important;
|
|
63
|
+
padding: 0 !important;
|
|
64
|
+
margin: 0 !important;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
table {
|
|
69
|
+
border-collapse: collapse !important;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
a {
|
|
73
|
+
color: #1a82e2;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
img {
|
|
77
|
+
height: auto;
|
|
78
|
+
line-height: 100%;
|
|
79
|
+
text-decoration: none;
|
|
80
|
+
border: 0;
|
|
81
|
+
outline: none;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.flagText {
|
|
85
|
+
/* font-family: 'Inter'; */
|
|
86
|
+
/* color: #667085 !important; */
|
|
87
|
+
font-size: 16px;
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
line-height: 24px;
|
|
90
|
+
text-align: left;
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
94
|
+
|
|
95
|
+
</head>
|
|
96
|
+
|
|
97
|
+
<body style="background-color: #dbe5ea;">
|
|
98
|
+
|
|
99
|
+
<div class="preheader"
|
|
100
|
+
style="display: none; max-width: 0; max-height: 0; overflow: hidden; font-size: 1px; line-height: 1px; color: #fff; opacity: 0;">
|
|
101
|
+
Email Summary (Hidden)
|
|
102
|
+
</div>
|
|
103
|
+
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="padding-left:10px;padding-right:10px">
|
|
104
|
+
<tr>
|
|
105
|
+
<td bgcolor="#dbe5ea" style="padding:32px 10px 0 10px">
|
|
106
|
+
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 680px;" align="center">
|
|
107
|
+
<tr>
|
|
108
|
+
<td class="o_bg-white o_px-md o_py-md o_sans o_text"
|
|
109
|
+
style="margin-top: 0px;margin-bottom: 0px;font-size: 16px;line-height: 24px;background-color: #ffffff;padding-left: 18px;padding-right: 24px;padding-top: 24px;padding-bottom: 24px;">
|
|
110
|
+
<p style="margin-top: 0px;margin-bottom: 0px;"><a class="o_text-white"
|
|
111
|
+
href="https://tangoeye.ai/"
|
|
112
|
+
style="text-decoration: none;outline: none;color: #ffffff;"><img
|
|
113
|
+
src="https://devtangoretail-api.tangoeye.ai/logo.png" width="200" height="100"
|
|
114
|
+
alt="SimpleApp"
|
|
115
|
+
style="-ms-interpolation-mode: bicubic;vertical-align: middle;border: 0;line-height: 100%;height: auto;outline: none;text-decoration: none;"></a>
|
|
116
|
+
</p>
|
|
117
|
+
</td>
|
|
118
|
+
</tr>
|
|
119
|
+
<tr>
|
|
120
|
+
<td align="left" bgcolor="#ffffff"
|
|
121
|
+
style="padding-left: 30px;padding-right: 24px; font-size: 14px; line-height: 24px;">
|
|
122
|
+
<p class="o_heading o_mb-xxs"
|
|
123
|
+
style="width: 624px;height: 0px;border: 1px solid #CBD5E1;flex: none;order: 1;flex-grow: 0;">
|
|
124
|
+
</p>
|
|
125
|
+
</td>
|
|
126
|
+
</tr>
|
|
127
|
+
<tr>
|
|
128
|
+
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
129
|
+
style="background-color: #ffffff;padding-left: 30px;padding-right: 24px;padding-bottom: 10px;">
|
|
130
|
+
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
131
|
+
style="margin-top: 0px;margin-bottom: 0px;font-size: 16px;line-height: 28px;color: #82899a;">
|
|
132
|
+
<span class="o_heading o_text-dark o_mb-xxs"
|
|
133
|
+
style="font-weight: 400;margin-top: 0px;margin-bottom: 4px;color: #121A26;line-height: 140%;">
|
|
134
|
+
Hi,<br />
|
|
135
|
+
Store compliance summary has been generated for a recently completed checklist across multiple stores. Review the
|
|
136
|
+
compliance performance and identify stores that require attention from the dashboard.
|
|
137
|
+
</span>
|
|
138
|
+
</div>
|
|
139
|
+
</td>
|
|
140
|
+
</tr>
|
|
141
|
+
<tr>
|
|
142
|
+
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
143
|
+
style="background-color: #ffffff;padding-left: 30px;padding-right: 24px;padding-bottom: 10px;">
|
|
144
|
+
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
145
|
+
style="margin-top: 0px;margin-bottom: 0px;font-size: 16px;line-height: 28px;color: #82899a;">
|
|
146
|
+
<span class="o_heading o_text-dark o_mb-xxs"
|
|
147
|
+
style="font-weight: 400;margin-top: 0px;margin-bottom: 4px;color: #121A26;line-height: 140%;">
|
|
148
|
+
Details of the checklist are as follows:
|
|
149
|
+
</span>
|
|
150
|
+
</div>
|
|
151
|
+
</td>
|
|
152
|
+
</tr>
|
|
153
|
+
</table>
|
|
154
|
+
</td>
|
|
155
|
+
</tr>
|
|
156
|
+
<tr>
|
|
157
|
+
<td align="center" bgcolor="#dbe5ea" style="padding:0 10px 0 10px">
|
|
158
|
+
<table align="center" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="0" width="100%"
|
|
159
|
+
style="max-width: 680px;">
|
|
160
|
+
<tr bgcolor="#ffffff" style="border:none;margin-top:0px;">
|
|
161
|
+
<td class="flagText" style="padding-left:30px; line-height: 24px;color:#000000">Checklist Name:
|
|
162
|
+
</td>
|
|
163
|
+
<td></td>
|
|
164
|
+
<td></td>
|
|
165
|
+
<td class="flagText">{{data.checklistName}}</td>
|
|
166
|
+
</tr>
|
|
167
|
+
<tr bgcolor="#ffffff" style="border:none;margin-top:3px;">
|
|
168
|
+
<td class="flagText" style="padding-left:30px; line-height: 24px;">Total Stores :</td>
|
|
169
|
+
<td></td>
|
|
170
|
+
<td></td>
|
|
171
|
+
<td class="flagText">{{data.total}}</td>
|
|
172
|
+
</tr>
|
|
173
|
+
|
|
174
|
+
<tr bgcolor="#ffffff" style="border:none;margin-top:3px;">
|
|
175
|
+
<td class="flagText" style="padding-left:30px; line-height: 24px;">Date :</td>
|
|
176
|
+
<td></td>
|
|
177
|
+
<td></td>
|
|
178
|
+
<td class="flagText">{{data.date}}</td>
|
|
179
|
+
</tr>
|
|
180
|
+
</table>
|
|
181
|
+
</td>
|
|
182
|
+
</tr>
|
|
183
|
+
<tr>
|
|
184
|
+
<td align="center" bgcolor="#dbe5ea" style="padding:0 10px 0 10px">
|
|
185
|
+
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 680px;">
|
|
186
|
+
<tr>
|
|
187
|
+
<td bgcolor="#ffffff" style="padding: 20px;padding-top:15px;padding-left:30px;">
|
|
188
|
+
<table border="0" cellpadding="0" cellspacing="0">
|
|
189
|
+
<tr>
|
|
190
|
+
<td align="center" bgcolor="#00A3FF" style="border-radius: 6px;height:50px;">
|
|
191
|
+
<a href="{{data.zipURL}}" target="_blank"
|
|
192
|
+
style="display: inline-block; padding: 16px 36px; font-size: 16px; color: #ffffff; text-decoration: none; border-radius: 6px;cursor:pointer">Download
|
|
193
|
+
</a>
|
|
194
|
+
</td>
|
|
195
|
+
</tr>
|
|
196
|
+
</table>
|
|
197
|
+
</td>
|
|
198
|
+
</tr>
|
|
199
|
+
</table>
|
|
200
|
+
</td>
|
|
201
|
+
</tr>
|
|
202
|
+
<tr>
|
|
203
|
+
<td align="center" bgcolor="#dbe5ea" style="padding:0 10px 32px 10px;">
|
|
204
|
+
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 680px;">
|
|
205
|
+
<tr>
|
|
206
|
+
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
207
|
+
style="background-color: #ffffff;padding-left: 30px;padding-right: 24px;padding-top:5px">
|
|
208
|
+
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
209
|
+
style="margin-top: 0px;margin-bottom: 0px;font-size: 12px;color: #202B3C;font-style: normal;font-weight: 400;font-size: 12px;line-height: 150%;">
|
|
210
|
+
<p>
|
|
211
|
+
If you have any questions or need assistance, please reach out to us at
|
|
212
|
+
support@tangotech.co.in.
|
|
213
|
+
</p>
|
|
214
|
+
</div>
|
|
215
|
+
</td>
|
|
216
|
+
</tr>
|
|
217
|
+
<tr>
|
|
218
|
+
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
219
|
+
style="background-color: #ffffff;padding-left: 30px;padding-right: 24px;padding-bottom:15px">
|
|
220
|
+
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
221
|
+
style="margin-top: 0px;margin-bottom: 0px;font-size: 12px;color: #202B3C;font-style: normal;font-weight: 400;font-size: 12px;line-height: 150%;">
|
|
222
|
+
<p>
|
|
223
|
+
© Tango Eye. All rights reserved.</p>
|
|
224
|
+
</div>
|
|
225
|
+
</td>
|
|
226
|
+
</tr>
|
|
227
|
+
</table>
|
|
228
|
+
</td>
|
|
229
|
+
</tr>
|
|
230
|
+
|
|
231
|
+
</table>
|
|
232
|
+
|
|
233
|
+
</body>
|
|
234
|
+
|
|
216
235
|
</html>
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
<div class="page">
|
|
177
177
|
<div class="detail-page">
|
|
178
178
|
{{#each this.sections}}
|
|
179
|
-
<div class="dp-header" {{#unless @first}}style="margin-top:20px"{{/unless}}><h2>{{this.sectionName}}</h2
|
|
179
|
+
<div class="dp-header" {{#unless @first}}style="margin-top:20px"{{/unless}}><h2>{{this.sectionName}}</h2>{{#if this.maxScore}}<span class="dp-score">{{this.currentScore}}/{{this.maxScore}}</span>{{/if}}</div>
|
|
180
180
|
<div class="sec-questions">
|
|
181
181
|
{{#each this.questions}}
|
|
182
182
|
<div class="q-row">
|