tango-app-api-trax 3.8.21 → 3.8.22-nike
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 +2 -2
- package/src/controllers/download.controller.js +19 -19
- package/src/controllers/gallery.controller.js +91 -27
- package/src/controllers/handlebar-helper.js +1 -0
- package/src/controllers/internalTrax.controller.js +808 -87
- package/src/controllers/mobileTrax.controller.js +262 -211
- package/src/controllers/teaxFlag.controller.js +5 -5
- package/src/controllers/trax.controller.js +6 -2
- package/src/hbs/recurringFlag.hbs +18 -16
- package/src/hbs/template.hbs +34 -23
- package/src/hbs/visit-checklist.hbs +84 -40
- package/src/hbs/weeklyWrap.hbs +218 -0
- package/src/routes/internalTraxApi.router.js +2 -0
- package/src/services/recurringFlagTracker.service.js +33 -33
- package/src/utils/visitChecklistPdf.utils.js +6 -5
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
6
|
+
<title>Weekly Wrap</title>
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
<style type="text/css">
|
|
9
|
+
body { font-family: "Inter", sans-serif !important; margin:0; padding:0; background:#dbe5ea; }
|
|
10
|
+
table { border-collapse: collapse; }
|
|
11
|
+
a { color:#1a82e2; }
|
|
12
|
+
.card {
|
|
13
|
+
background:#F4F8FB;
|
|
14
|
+
border-radius:8px;
|
|
15
|
+
padding:20px 22px;
|
|
16
|
+
}
|
|
17
|
+
.cardLabel { font-size:13px; color:#475569; margin-bottom:6px; }
|
|
18
|
+
.cardValue { font-size:22px; font-weight:700; color:#0F172A; }
|
|
19
|
+
.wow { font-size:12px; font-weight:600; margin-left:6px; }
|
|
20
|
+
.wow.up { color:#16A34A; }
|
|
21
|
+
.wow.down { color:#DC2626; }
|
|
22
|
+
.wowLabel { font-size:11px; color:#94A3B8; margin-left:4px; }
|
|
23
|
+
.sectionTitle { font-size:16px; font-weight:700; color:#0F172A; margin:18px 0 10px; }
|
|
24
|
+
.breakdownRow { font-size:14px; color:#1E293B; line-height:24px; }
|
|
25
|
+
.insightCard {
|
|
26
|
+
background:#EFF7FF;
|
|
27
|
+
border-radius:8px;
|
|
28
|
+
padding:20px 22px;
|
|
29
|
+
}
|
|
30
|
+
.attach {
|
|
31
|
+
background:#F1F5F9;
|
|
32
|
+
border-radius:8px;
|
|
33
|
+
padding:12px 14px;
|
|
34
|
+
display:flex;
|
|
35
|
+
align-items:center;
|
|
36
|
+
gap:10px;
|
|
37
|
+
font-size:13px;
|
|
38
|
+
color:#0F172A;
|
|
39
|
+
}
|
|
40
|
+
.ctaBtn {
|
|
41
|
+
display:inline-block;
|
|
42
|
+
background:#00A3FF;
|
|
43
|
+
color:#FFFFFF !important;
|
|
44
|
+
padding:14px 36px;
|
|
45
|
+
font-weight:600;
|
|
46
|
+
font-size:15px;
|
|
47
|
+
border-radius:8px;
|
|
48
|
+
text-decoration:none;
|
|
49
|
+
}
|
|
50
|
+
.footerText { font-size:12px; color:#475569; line-height:18px; }
|
|
51
|
+
</style>
|
|
52
|
+
</head>
|
|
53
|
+
<body>
|
|
54
|
+
<table width="100%" cellpadding="0" cellspacing="0" style="background:#dbe5ea;padding:24px 10px;">
|
|
55
|
+
<tr>
|
|
56
|
+
<td align="center" style="padding-top:10px;padding-bottom:10px">
|
|
57
|
+
<table width="100%" cellpadding="0" cellspacing="0" style="max-width:680px;background:#FFFFFF;border:1px dashed #93B6CC;border-radius:10px;overflow:hidden;">
|
|
58
|
+
|
|
59
|
+
{{!-- Header --}}
|
|
60
|
+
<tr>
|
|
61
|
+
<td style="padding:20px 24px 0 24px;">
|
|
62
|
+
<img src="https://devtangoretail-api.tangoeye.ai/logo.png" width="160" alt="TangoEye"/>
|
|
63
|
+
</td>
|
|
64
|
+
</tr>
|
|
65
|
+
|
|
66
|
+
{{!-- Banner --}}
|
|
67
|
+
<tr>
|
|
68
|
+
<td style="padding:14px 24px 0 24px;">
|
|
69
|
+
<div style="position:relative;background:#1F2A37;border-radius:10px;color:#FFFFFF;padding:36px 20px;text-align:center;">
|
|
70
|
+
<div style="font-size:22px;font-weight:700;">Weekly Wrap</div>
|
|
71
|
+
<div style="font-size:13px;color:#CBD5E1;margin-top:6px;">
|
|
72
|
+
Your Store's Flags Insights for {{data.startDate}} - {{data.endDate}}
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</td>
|
|
76
|
+
</tr>
|
|
77
|
+
|
|
78
|
+
{{!-- Greeting --}}
|
|
79
|
+
<tr>
|
|
80
|
+
<td style="padding:18px 24px 0 24px;font-size:14px;color:#1E293B;line-height:22px;">
|
|
81
|
+
Hi Team,<br/>
|
|
82
|
+
Here is your weekly checklist insights report, highlighting key observations, recurring issues, and areas that may require attention to improve store performance and compliance.
|
|
83
|
+
</td>
|
|
84
|
+
</tr>
|
|
85
|
+
|
|
86
|
+
{{!-- Weekly Overview --}}
|
|
87
|
+
<tr>
|
|
88
|
+
<td style="padding:8px 24px 0 24px;">
|
|
89
|
+
<div class="sectionTitle">Weekly Overview</div>
|
|
90
|
+
<table width="100%" cellpadding="0" cellspacing="8">
|
|
91
|
+
<tr>
|
|
92
|
+
<td width="30%" style="padding-right:10px">
|
|
93
|
+
<div class="card">
|
|
94
|
+
<div class="cardLabel">Stores Flagged</div>
|
|
95
|
+
<div>
|
|
96
|
+
<span class="cardValue">{{data.storesFlagged}}</span>
|
|
97
|
+
{{#if data.storesFlaggedWow.value}}
|
|
98
|
+
<span class="wow {{data.storesFlaggedWow.direction}}">{{#eq data.storesFlaggedWow.direction "up"}}↗{{else}}↘{{/eq}} {{data.storesFlaggedWow.value}}</span>
|
|
99
|
+
<span class="wowLabel">WoW</span>
|
|
100
|
+
{{/if}}
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
</td>
|
|
104
|
+
<td width="30%" style="padding-right:10px">
|
|
105
|
+
<div class="card">
|
|
106
|
+
<div class="cardLabel">Total Flags</div>
|
|
107
|
+
<div>
|
|
108
|
+
<span class="cardValue">{{data.totalFlags}}</span>
|
|
109
|
+
{{#if data.totalFlagsWow.value}}
|
|
110
|
+
<span class="wow {{data.totalFlagsWow.direction}}">{{#eq data.totalFlagsWow.direction "up"}}↗{{else}}↘{{/eq}} {{data.totalFlagsWow.value}}</span>
|
|
111
|
+
<span class="wowLabel">WoW</span>
|
|
112
|
+
{{/if}}
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</td>
|
|
116
|
+
<td width="30%" style="padding-right:10px">
|
|
117
|
+
<div class="card">
|
|
118
|
+
<div class="cardLabel">Checklist Flags</div>
|
|
119
|
+
<div>
|
|
120
|
+
<span class="cardValue">{{data.checklistFlags}}</span>
|
|
121
|
+
{{#if data.checklistFlagsWow.value}}
|
|
122
|
+
<span class="wow {{data.checklistFlagsWow.direction}}">{{#eq data.checklistFlagsWow.direction "up"}}↗{{else}}↘{{/eq}} {{data.checklistFlagsWow.value}}</span>
|
|
123
|
+
<span class="wowLabel">WoW</span>
|
|
124
|
+
{{/if}}
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</td>
|
|
128
|
+
</tr>
|
|
129
|
+
</table>
|
|
130
|
+
</td>
|
|
131
|
+
</tr>
|
|
132
|
+
|
|
133
|
+
{{!-- Flags Breakdown --}}
|
|
134
|
+
<tr>
|
|
135
|
+
<td style="padding:8px 24px 0 24px;">
|
|
136
|
+
<div class="sectionTitle">Flags Breakdown</div>
|
|
137
|
+
<div class="breakdownRow">
|
|
138
|
+
Question Flags : {{data.questionFlags}}
|
|
139
|
+
Not Submitted Flags : {{data.notSubmittedFlags}}
|
|
140
|
+
Run AI Flags : {{data.runAIFlags}}
|
|
141
|
+
Recurring Flags : {{data.recurringFlags}}
|
|
142
|
+
</div>
|
|
143
|
+
</td>
|
|
144
|
+
</tr>
|
|
145
|
+
|
|
146
|
+
{{!-- Key Insights --}}
|
|
147
|
+
<tr>
|
|
148
|
+
<td style="padding:8px 24px 0 24px;">
|
|
149
|
+
<div class="sectionTitle">Key Insights</div>
|
|
150
|
+
<table width="100%" cellpadding="0" cellspacing="8">
|
|
151
|
+
<tr>
|
|
152
|
+
<td width="40%" style="padding-right:10px">
|
|
153
|
+
<div class="insightCard">
|
|
154
|
+
<div class="cardLabel">Highest Flagged Store</div>
|
|
155
|
+
<div>
|
|
156
|
+
<span class="cardValue">{{data.highestFlaggedStore}}</span>
|
|
157
|
+
{{#if data.highestFlaggedStoreWow.value}}
|
|
158
|
+
<span class="wow {{data.highestFlaggedStoreWow.direction}}">{{#eq data.highestFlaggedStoreWow.direction "up"}}↗{{else}}↘{{/eq}} {{data.highestFlaggedStoreWow.value}}</span>
|
|
159
|
+
<span class="wowLabel">WoW</span>
|
|
160
|
+
{{/if}}
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</td>
|
|
164
|
+
<td width="40%">
|
|
165
|
+
<div class="insightCard">
|
|
166
|
+
<div class="cardLabel">Highest Recurring Flagged Store</div>
|
|
167
|
+
<div>
|
|
168
|
+
<span class="cardValue">{{data.highestRecurringStore}}</span>
|
|
169
|
+
{{#if data.highestRecurringStoreWow.value}}
|
|
170
|
+
<span class="wow {{data.highestRecurringStoreWow.direction}}">{{#eq data.highestRecurringStoreWow.direction "up"}}↗{{else}}↘{{/eq}} {{data.highestRecurringStoreWow.value}}</span>
|
|
171
|
+
<span class="wowLabel">WoW</span>
|
|
172
|
+
{{/if}}
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</td>
|
|
176
|
+
</tr>
|
|
177
|
+
</table>
|
|
178
|
+
</td>
|
|
179
|
+
</tr>
|
|
180
|
+
|
|
181
|
+
{{!-- Attachment hint --}}
|
|
182
|
+
<tr>
|
|
183
|
+
<td style="padding:18px 24px 0 24px;">
|
|
184
|
+
<div style="color:#1D2939;font-family: Inter;font-weight: 400;font-style: Regular;font-size: 14px;leading-trim: NONE;line-height: 100%;letter-spacing: 0.2px;">
|
|
185
|
+
Refer to the attached report for the weekly summary of the stores assigned to you.
|
|
186
|
+
</div>
|
|
187
|
+
<div style="color:#384860;font-family: Inter;font-weight: 400;font-style: Regular;font-size: 10px;leading-trim: NONE;line-height: 150%;letter-spacing: 0.2px;padding-top:10px">
|
|
188
|
+
If you have any questions or need assistance, please reach out to us at support@tangotech.co.in.
|
|
189
|
+
</div>
|
|
190
|
+
{{!-- <div class="attach">
|
|
191
|
+
<span style="display:inline-block;width:22px;height:22px;background:#21A366;color:#FFFFFF;border-radius:4px;text-align:center;line-height:22px;font-size:12px;font-weight:700;">X</span>
|
|
192
|
+
<span><b>{{data.attachmentName}}</b>{{#if data.attachmentSize}} <span style="color:#94A3B8;">{{data.attachmentSize}}</span>{{/if}}</span>
|
|
193
|
+
</div> --}}
|
|
194
|
+
</td>
|
|
195
|
+
</tr>
|
|
196
|
+
|
|
197
|
+
{{!-- CTA --}}
|
|
198
|
+
<tr>
|
|
199
|
+
<td style="padding:18px 24px 8px 24px;text-align:center;">
|
|
200
|
+
<a href="{{data.domain}}" class="ctaBtn">View Detailed Insights</a>
|
|
201
|
+
</td>
|
|
202
|
+
</tr>
|
|
203
|
+
|
|
204
|
+
{{!-- Footer --}}
|
|
205
|
+
<tr>
|
|
206
|
+
<td style="padding:18px 24px 24px 24px;border-top:1px solid #E2E8F0;">
|
|
207
|
+
<div class="footerText">
|
|
208
|
+
©2024 Tango IT Solutions India Pvt. Ltd. All rights reserved.<br/>
|
|
209
|
+
Old Number 12 and New, 39, Haddows Rd, Thousand Lights West, Nungambakkam, Chennai, Tamil Nadu 600006
|
|
210
|
+
</div>
|
|
211
|
+
</td>
|
|
212
|
+
</tr>
|
|
213
|
+
</table>
|
|
214
|
+
</td>
|
|
215
|
+
</tr>
|
|
216
|
+
</table>
|
|
217
|
+
</body>
|
|
218
|
+
</html>
|
|
@@ -37,7 +37,9 @@ internalTraxRouter
|
|
|
37
37
|
.post( '/getSubmissionDetails', isAllowedInternalAPIHandler, internalController.checklistTaskSubmissionDetails )
|
|
38
38
|
.post( '/posblock', isAllowedInternalAPIHandler, internalController.getStoreTaskDetails )
|
|
39
39
|
.post( '/runAIFlag', isAllowedInternalAPIHandler, internalController.runAIFlag )
|
|
40
|
+
.post( '/incrementRunAIRecurring', isAllowedInternalAPIHandler, internalController.incrementRunAIRecurring )
|
|
40
41
|
.post( '/recurringFlag', isAllowedInternalAPIHandler, internalController.recurringFlagAlert )
|
|
42
|
+
.post( '/weeklyWrap', isAllowedInternalAPIHandler, internalController.weeklyWrapAlert )
|
|
41
43
|
.post( '/downloadInsertPdf', isAllowedInternalAPIHandler, internalController.downloadInsertPdf )
|
|
42
44
|
.get( '/checklistAutoMailList', isAllowedInternalAPIHandler, internalController.checklistAutoMailList )
|
|
43
45
|
.post( '/sendAIEmailList', isAllowedInternalAPIHandler, internalController.sendAIEmailList )
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import model from 'tango-api-schema';
|
|
2
|
-
|
|
3
|
-
export const findOne = async ( query={}, field={} ) => {
|
|
4
|
-
return model.recurringFlagTrackerModel.findOne( query, field );
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export const find = async ( query={}, field={} ) => {
|
|
8
|
-
return model.recurringFlagTrackerModel.find( query, field );
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const create = async ( document = {} ) => {
|
|
12
|
-
return model.recurringFlagTrackerModel.create( document );
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const updateOne = async ( query = {}, record={} ) => {
|
|
16
|
-
return model.recurringFlagTrackerModel.updateOne( query, { $set: record }, { upsert: true } );
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const updateMany = async ( query = {}, record={} ) => {
|
|
20
|
-
return model.recurringFlagTrackerModel.updateMany( query, { $set: record } );
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const deleteOne = async ( query = {} ) => {
|
|
24
|
-
return model.recurringFlagTrackerModel.deleteOne( query );
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const aggregate = async ( query = [] ) => {
|
|
28
|
-
return model.recurringFlagTrackerModel.aggregate( query );
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const bulkWrite = async ( ops = [] ) => {
|
|
32
|
-
return model.recurringFlagTrackerModel.bulkWrite( ops );
|
|
33
|
-
};
|
|
1
|
+
import model from 'tango-api-schema';
|
|
2
|
+
|
|
3
|
+
export const findOne = async ( query={}, field={} ) => {
|
|
4
|
+
return model.recurringFlagTrackerModel.findOne( query, field );
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const find = async ( query={}, field={} ) => {
|
|
8
|
+
return model.recurringFlagTrackerModel.find( query, field );
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const create = async ( document = {} ) => {
|
|
12
|
+
return model.recurringFlagTrackerModel.create( document );
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const updateOne = async ( query = {}, record={} ) => {
|
|
16
|
+
return model.recurringFlagTrackerModel.updateOne( query, { $set: record }, { upsert: true } );
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const updateMany = async ( query = {}, record={} ) => {
|
|
20
|
+
return model.recurringFlagTrackerModel.updateMany( query, { $set: record } );
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const deleteOne = async ( query = {} ) => {
|
|
24
|
+
return model.recurringFlagTrackerModel.deleteOne( query );
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const aggregate = async ( query = [] ) => {
|
|
28
|
+
return model.recurringFlagTrackerModel.aggregate( query );
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const bulkWrite = async ( ops = [] ) => {
|
|
32
|
+
return model.recurringFlagTrackerModel.bulkWrite( ops );
|
|
33
|
+
};
|
|
@@ -169,13 +169,15 @@ function buildQuestionAnswerEntries( question ) {
|
|
|
169
169
|
|
|
170
170
|
const rawMultiRefSources = [
|
|
171
171
|
userAnswer?.multiReferenceImage,
|
|
172
|
-
matchedAnswer?.multiReferenceImage,
|
|
173
|
-
question?.answers?.[0]?.multiReferenceImage,
|
|
172
|
+
// matchedAnswer?.multiReferenceImage,
|
|
173
|
+
// question?.answers?.[0]?.multiReferenceImage,
|
|
174
174
|
];
|
|
175
175
|
let multiReferenceImage = [];
|
|
176
176
|
for ( const src of rawMultiRefSources ) {
|
|
177
177
|
const flat = flattenImageRefs( src );
|
|
178
|
-
if ( flat.length ) {
|
|
178
|
+
if ( flat.length ) {
|
|
179
|
+
multiReferenceImage = flat; break;
|
|
180
|
+
}
|
|
179
181
|
}
|
|
180
182
|
const validationImage = flattenImageRefs( userAnswer?.validationImage );
|
|
181
183
|
|
|
@@ -442,7 +444,7 @@ export function buildVisitChecklistTemplateDataFromProcessed( processedDoc, bran
|
|
|
442
444
|
|
|
443
445
|
const checklistName = doc.checkListName || 'Visit Checklist';
|
|
444
446
|
|
|
445
|
-
const refFromId = doc._id && String( doc._id ).length > 8 ? String( doc._id ).slice( -8 ).toUpperCase() : ( doc._id ? String( doc._id ) : '--' );
|
|
447
|
+
// const refFromId = doc._id && String( doc._id ).length > 8 ? String( doc._id ).slice( -8 ).toUpperCase() : ( doc._id ? String( doc._id ) : '--' );
|
|
446
448
|
|
|
447
449
|
const { titleLine1, titleLine2 } = splitCoverTitle( checklistName );
|
|
448
450
|
|
|
@@ -920,7 +922,6 @@ export function resolveTemplateUrls( templateData, baseUrl = 'https://d1r0hc2ssk
|
|
|
920
922
|
q.multiQuestionReferenceImage = q.multiQuestionReferenceImage.map( ( ele ) => resolveUrl( ele ) );
|
|
921
923
|
}
|
|
922
924
|
q.userAnswer?.forEach( ( ua ) => {
|
|
923
|
-
|
|
924
925
|
if ( ua.multiReferenceImage?.length ) {
|
|
925
926
|
ua.multiReferenceImage = ua.multiReferenceImage.map( ( ele ) => resolveUrl( ele ) );
|
|
926
927
|
}
|