tango-app-api-client 3.0.0 → 3.0.2
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 +7 -3
- package/src/controllers/client.controllers.js +577 -3
- package/src/dtos/client.dtos.js +231 -0
- package/src/routes/client.routes.js +24 -6
- package/src/service/camera.service.js +9 -0
- package/src/service/client.service.js +239 -8
- package/src/service/store.service.js +9 -0
- package/src/service/user.service.js +9 -0
- package/src/services/client.services.js +263 -0
- package/src/validations/client.validations.js +22 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tango-app-api-client",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "client",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -14,13 +14,17 @@
|
|
|
14
14
|
"license": "ISC",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"aws-sdk": "^2.1560.0",
|
|
17
|
+
"cors": "^2.8.5",
|
|
17
18
|
"dotenv": "^16.4.4",
|
|
18
19
|
"express": "^4.18.2",
|
|
20
|
+
"express-fileupload": "^1.4.3",
|
|
19
21
|
"handlebars": "^4.7.8",
|
|
22
|
+
"joi": "^17.12.1",
|
|
23
|
+
"lodash": "^4.17.21",
|
|
20
24
|
"mongodb": "^6.3.0",
|
|
21
25
|
"nodemon": "^3.0.3",
|
|
22
|
-
"tango-api-schema": "^2.0.
|
|
23
|
-
"tango-app-api-middleware": "^1.0.
|
|
26
|
+
"tango-api-schema": "^2.0.33",
|
|
27
|
+
"tango-app-api-middleware": "^1.0.23",
|
|
24
28
|
"winston": "^3.11.0",
|
|
25
29
|
"winston-daily-rotate-file": "^5.0.0"
|
|
26
30
|
},
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { billingDetailsUpdate, brandInfoUpdate, domainDetailsConfigurationUpdate, featureConfigurationUpdate, getClientData, signatoryDetailsUpdate, ticketConfigurationUpdate, documentsUpdate, getUserData, auditConfigurationUpdate, auditConfigurationGet, CsmUsersGet, OpsUsersGet, userConfigurationUpdate, findClient, aggregateClient, createAuditQueue, findOne, getClientCount, insert, update } from '../service/client.service.js';
|
|
2
|
+
import { checkFileExist, fileUpload, signedUrl, chunkArray, download, logger } from 'tango-app-api-middleware';
|
|
3
|
+
import { countDocumentsUser, findOneUser } from '../service/user.service.js';
|
|
4
|
+
import { aggregateStore, countDocumentsStore } from '../service/store.service.js';
|
|
5
|
+
import { aggregateCamera, countDocumentsCamera } from '../service/camera.service.js';
|
|
6
|
+
import _ from 'lodash';
|
|
3
7
|
|
|
4
8
|
export async function create( req, res ) {
|
|
5
9
|
try {
|
|
@@ -62,7 +66,7 @@ export async function changeStatus( req, res, next ) {
|
|
|
62
66
|
export async function getClients( req, res ) {
|
|
63
67
|
try {
|
|
64
68
|
const field = { clientName: 1, clientId: 1 };
|
|
65
|
-
const result = await
|
|
69
|
+
const result = await findClient( {}, field );
|
|
66
70
|
if ( result == 0 ) {
|
|
67
71
|
return res.sendError( 'No Data Found', 204 );
|
|
68
72
|
}
|
|
@@ -72,3 +76,573 @@ export async function getClients( req, res ) {
|
|
|
72
76
|
return res.sendError( error, 500 );
|
|
73
77
|
}
|
|
74
78
|
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
export async function clientDetails( req, res ) {
|
|
82
|
+
try {
|
|
83
|
+
const client = await getClientData( { id: req.params.id } );
|
|
84
|
+
if ( client ) {
|
|
85
|
+
const isLogoExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `${client.clientId}/logo/${client.profileDetails?.logo}` } );
|
|
86
|
+
const isGstCertificateExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `${client.clientId}/documents/${client.document?.gst?.path}` } );
|
|
87
|
+
const isAddressCertificateExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `${client.clientId}/documents/${client.document?.addressProof?.path}` } );
|
|
88
|
+
const isPanCertificateExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `${client.clientId}/documents/${client.document?.pan?.path}` } );
|
|
89
|
+
const isCinCertificateExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `${client.clientId}/documents/${client.document?.cin?.path}` } );
|
|
90
|
+
const isContractCertificateExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `documents/contract.pdf` } );
|
|
91
|
+
const isTermsAndConditionsExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `documents/terms&conditions.pdf` } );
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if ( isLogoExist ) {
|
|
95
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `${client.clientId}/logo/${client.profileDetails?.logo}` } );
|
|
96
|
+
client.profileDetails.logo = signedFilUrl;
|
|
97
|
+
} else {
|
|
98
|
+
client.profileDetails.logo = '';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if ( isGstCertificateExist ) {
|
|
102
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `${client.clientId}/documents/${client.document?.gst?.path}` } );
|
|
103
|
+
client.document.gst.path = signedFilUrl;
|
|
104
|
+
} else {
|
|
105
|
+
client.document.gst.path = '';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if ( isAddressCertificateExist ) {
|
|
109
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `${client.clientId}/documents/${client.document?.addressProof?.path}` } );
|
|
110
|
+
client.document.addressProof.path = signedFilUrl;
|
|
111
|
+
} else {
|
|
112
|
+
client.document.addressProof.path = '';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if ( isPanCertificateExist ) {
|
|
116
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `${client.clientId}/documents/${client.document?.pan?.path}` } );
|
|
117
|
+
client.document.pan.path = signedFilUrl;
|
|
118
|
+
} else {
|
|
119
|
+
client.document.pan.path = '';
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if ( isCinCertificateExist ) {
|
|
123
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `${client.clientId}/documents/${client.document?.cin?.path}` } );
|
|
124
|
+
client.document.cin.path = signedFilUrl;
|
|
125
|
+
} else {
|
|
126
|
+
client.document.cin.path = '';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if ( isContractCertificateExist ) {
|
|
130
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `documents/contract.pdf` } );
|
|
131
|
+
client._doc.document.contract = signedFilUrl;
|
|
132
|
+
} else {
|
|
133
|
+
client._doc.document.contract = '';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if ( isTermsAndConditionsExist ) {
|
|
137
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `documents/terms&conditions.pdf` } );
|
|
138
|
+
client._doc.document.termsAndconditions = signedFilUrl;
|
|
139
|
+
} else {
|
|
140
|
+
client._doc.document.termsAndconditions = '';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const user = await getUserData( { id: client.userId } );
|
|
144
|
+
const userData = {
|
|
145
|
+
corporateEmail: user?.email,
|
|
146
|
+
countryCode: user?.countryCode,
|
|
147
|
+
mobileNumber: user?.mobileNumber,
|
|
148
|
+
};
|
|
149
|
+
return res.sendSuccess( { userData, ...client._doc } );
|
|
150
|
+
} else {
|
|
151
|
+
return res.sendError( 'Client not found', 404 );
|
|
152
|
+
}
|
|
153
|
+
} catch ( error ) {
|
|
154
|
+
logger.error( { error: error, message: req.params, function: 'clientDetails' } );
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export async function detailedAllClientCount( req, res ) {
|
|
158
|
+
try {
|
|
159
|
+
const query = [
|
|
160
|
+
{
|
|
161
|
+
$project: {
|
|
162
|
+
activeClient: { $cond: [ { $eq: [ '$status', 'active' ] }, 1, 0 ] },
|
|
163
|
+
paidClient: { $cond: [ { $eq: [ '$status', 'paid' ] }, 1, 0 ] },
|
|
164
|
+
trialClient: { $cond: [ { $eq: [ '$status', 'trial' ] }, 1, 0 ] },
|
|
165
|
+
freeClient: { $cond: [ { $eq: [ '$status', 'free' ] }, 1, 0 ] },
|
|
166
|
+
holdClient: { $cond: [ { $eq: [ '$status', 'hold' ] }, 1, 0 ] },
|
|
167
|
+
suspendClient: { $cond: [ { $eq: [ '$status', 'suspend' ] }, 1, 0 ] },
|
|
168
|
+
deactiveClient: { $cond: [ { $eq: [ '$status', 'deactive' ] }, 1, 0 ] },
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
$group: {
|
|
173
|
+
_id: null,
|
|
174
|
+
totalCount: { $sum: 1 },
|
|
175
|
+
activeClient: { $sum: '$activeClient' },
|
|
176
|
+
paidClient: { $sum: '$paidClient' },
|
|
177
|
+
trialClient: { $sum: '$trialClient' },
|
|
178
|
+
freeClient: { $sum: '$freeClient' },
|
|
179
|
+
holdClient: { $sum: '$holdClient' },
|
|
180
|
+
suspendClient: { $sum: '$suspendClient' },
|
|
181
|
+
deactiveClient: { $sum: '$deactiveClient' },
|
|
182
|
+
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
];
|
|
186
|
+
const result = await aggregateClient( query );
|
|
187
|
+
if ( result == 0 ) {
|
|
188
|
+
return res.sendError( 'No Data Found', 204 );
|
|
189
|
+
}
|
|
190
|
+
return res.sendSuccess( { result: result } );
|
|
191
|
+
} catch ( error ) {
|
|
192
|
+
logger.error( { error: error, function: 'detailedAllClientCount' } );
|
|
193
|
+
return res.sendError( error, 500 );
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export async function updateBrandInfo( req, res ) {
|
|
198
|
+
try {
|
|
199
|
+
if ( req.files?.logo ) {
|
|
200
|
+
const uploadDataParams = {
|
|
201
|
+
Bucket: 'sandbox-tango-client',
|
|
202
|
+
Key: `${req.params.id}/logo/`,
|
|
203
|
+
fileName: `brandLogo.${req.files.logo.name.split( '.' )[1]}`,
|
|
204
|
+
ContentType: req.files.logo.mimetype,
|
|
205
|
+
body: req.files.logo.data,
|
|
206
|
+
};
|
|
207
|
+
await fileUpload( uploadDataParams );
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const updateAck = await brandInfoUpdate( {
|
|
211
|
+
clientId: req.params?.id, registeredCompanyName: req.body?.registeredCompanyName, industry: req.body?.industry,
|
|
212
|
+
clientType: req.body?.clientType, registeredAddress: req.body?.registeredAddress, headQuarters: req.body?.headQuarters,
|
|
213
|
+
website: req.body?.website, status: req.body?.status, logo: req.logo?.logo ? `brandLogo.${req.files.logo.name.split( '.' )[1]}` : undefined,
|
|
214
|
+
} );
|
|
215
|
+
if ( updateAck ) {
|
|
216
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
217
|
+
}
|
|
218
|
+
} catch ( error ) {
|
|
219
|
+
logger.error( { error: error, message: req.params, function: 'updateBrandInfo' } );
|
|
220
|
+
return res.sendError( error, 500 );
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export async function updateBillingDetails( req, res ) {
|
|
225
|
+
try {
|
|
226
|
+
if ( req.files?.gstCertificate ) {
|
|
227
|
+
const uploadDataParams = {
|
|
228
|
+
Bucket: 'sandbox-tango-client',
|
|
229
|
+
Key: `${req.params.id}/documents/`,
|
|
230
|
+
fileName: `gstCertificate.${req.files.gstCertificate.name.split( '.' )[1]}`,
|
|
231
|
+
ContentType: req.files.gstCertificate.mimetype,
|
|
232
|
+
body: req.files.gstCertificate.data,
|
|
233
|
+
};
|
|
234
|
+
await fileUpload( uploadDataParams );
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const updateAck = await billingDetailsUpdate( {
|
|
238
|
+
clientId: req.params?.id, tradeName: req.body?.tradeName, gstNumber: req.body?.gstNumber,
|
|
239
|
+
authorityName: req.body?.authorityName, authorityEmail: req.body?.authorityEmail, billingAddress: req.body?.billingAddress,
|
|
240
|
+
gstCertificate: req.files?.gstCertificate ? `gstCertificate.${req.files?.gstCertificate.name.split( '.' )[1]}` : undefined,
|
|
241
|
+
} );
|
|
242
|
+
if ( updateAck ) {
|
|
243
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
244
|
+
}
|
|
245
|
+
} catch ( error ) {
|
|
246
|
+
logger.error( { error: error, message: req.params, function: 'updateBillingDetails' } );
|
|
247
|
+
return res.sendError( error, 500 );
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export async function updateSignatoryDetails( req, res ) {
|
|
252
|
+
try {
|
|
253
|
+
const updateAck = await signatoryDetailsUpdate( {
|
|
254
|
+
clientId: req.params?.id, name: req.body?.name, email: req.body?.email,
|
|
255
|
+
number: req.body?.number, designation: req.body?.designation,
|
|
256
|
+
} );
|
|
257
|
+
if ( updateAck ) {
|
|
258
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
259
|
+
}
|
|
260
|
+
} catch ( error ) {
|
|
261
|
+
logger.error( { error: error, message: req.params, function: 'updateSignatoryDetails' } );
|
|
262
|
+
return res.sendError( error, 500 );
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export async function updateTicketConfiguration( req, res ) {
|
|
267
|
+
try {
|
|
268
|
+
const updateAck = await ticketConfigurationUpdate( {
|
|
269
|
+
clientId: req.params?.id, MinFilesCount: req.body?.MinFilesCount, accuracyPercentage: req.body?.accuracyPercentage, downTimeType: req.body?.downTimeType,
|
|
270
|
+
infraDownTime: req.body?.infraDownTime, installationReAssign: req.body?.installationReAssign, isRcaTicketAssign: req.body?.isRcaTicketAssign,
|
|
271
|
+
isRefreshAlert: req.body?.isRefreshAlert, isStatusCheckAlert: req.body?.isStatusCheckAlert, rcaTicketAssign: req.body?.rcaTicketAssign, reTrain: req.body?.reTrain,
|
|
272
|
+
refreshAlert: req.body?.refreshAlert, sendToAdmin: req.body?.sendToAdmin, sendToUser: req.body?.sendToUser, statusCheckAlert: req.body?.statusCheckAlert,
|
|
273
|
+
} );
|
|
274
|
+
if ( updateAck ) {
|
|
275
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
276
|
+
}
|
|
277
|
+
} catch ( error ) {
|
|
278
|
+
logger.error( { error: error, message: req.params, function: 'updateTicketConfiguration' } );
|
|
279
|
+
return res.sendError( error, 500 );
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export async function updateFeatureConfiguration( req, res ) {
|
|
284
|
+
try {
|
|
285
|
+
const updateAck = await featureConfigurationUpdate( {
|
|
286
|
+
clientId: req.params?.id, billableCalculation: req.body?.billableCalculation, bouncedLimitCondition: req.body?.bouncedLimitCondition, bouncedLimitValue: req.body?.bouncedLimitValue,
|
|
287
|
+
close: req.body?.close, conversionCalculation: req.body?.conversionCalculation, conversionCondition: req.body?.conversionCondition,
|
|
288
|
+
conversionValue: req.body?.conversionValue, infraAlertCondition: req.body?.infraAlertCondition, infraAlertValue: req.body?.infraAlertValue, isFootfallDirectory: req.body?.isFootfallDirectory,
|
|
289
|
+
isNormalized: req.body?.isNormalized, isPasserByData: req.body?.isPasserByData, missedOpportunityCalculation: req.body?.missedOpportunityCalculation, open: req.body?.open,
|
|
290
|
+
} );
|
|
291
|
+
if ( updateAck ) {
|
|
292
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
293
|
+
}
|
|
294
|
+
} catch ( error ) {
|
|
295
|
+
logger.error( { error: error, message: req.params, function: 'updateTicketConfiguration' } );
|
|
296
|
+
return res.sendError( error, 500 );
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export async function domainDetailsConfiguration( req, res ) {
|
|
301
|
+
try {
|
|
302
|
+
const updateAck = await domainDetailsConfigurationUpdate( {
|
|
303
|
+
clientId: req.params?.id, domainName: req.body?.domainName, isEnable: req.body?.isEnable,
|
|
304
|
+
} );
|
|
305
|
+
if ( updateAck ) {
|
|
306
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
307
|
+
}
|
|
308
|
+
} catch ( error ) {
|
|
309
|
+
logger.error( { error: error, message: req.params, function: 'domainDetailsConfiguration' } );
|
|
310
|
+
return res.sendError( error, 500 );
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export async function userConfiguration( req, res ) {
|
|
315
|
+
try {
|
|
316
|
+
const updateAck = await userConfigurationUpdate( {
|
|
317
|
+
clientId: req.params?.id, csm: req.body?.csm, ops: req.body?.ops,
|
|
318
|
+
} );
|
|
319
|
+
if ( updateAck ) {
|
|
320
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
321
|
+
}
|
|
322
|
+
} catch ( error ) {
|
|
323
|
+
logger.error( { error: error, message: req.params, function: 'userConfiguration' } );
|
|
324
|
+
return res.sendError( error, 500 );
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export async function updateDocuments( req, res ) {
|
|
329
|
+
try {
|
|
330
|
+
if ( req.files?.addressDoc ) {
|
|
331
|
+
const uploadDataParams = {
|
|
332
|
+
Bucket: 'sandbox-tango-client',
|
|
333
|
+
Key: `${req.params.id}/documents/`,
|
|
334
|
+
fileName: `addressCertificate.${req.files.addressDoc.name.split( '.' )[1]}`,
|
|
335
|
+
ContentType: req.files.addressDoc.mimetype,
|
|
336
|
+
body: req.files.addressDoc.data,
|
|
337
|
+
};
|
|
338
|
+
await fileUpload( uploadDataParams );
|
|
339
|
+
}
|
|
340
|
+
if ( req.files?.gstDoc ) {
|
|
341
|
+
const uploadDataParams = {
|
|
342
|
+
Bucket: 'sandbox-tango-client',
|
|
343
|
+
Key: `${req.params.id}/documents/`,
|
|
344
|
+
fileName: `gstCertificate.${req.files.gstDoc.name.split( '.' )[1]}`,
|
|
345
|
+
ContentType: req.files.gstDoc.mimetype,
|
|
346
|
+
body: req.files.gstDoc.data,
|
|
347
|
+
};
|
|
348
|
+
await fileUpload( uploadDataParams );
|
|
349
|
+
}
|
|
350
|
+
if ( req.files?.panDoc ) {
|
|
351
|
+
const uploadDataParams = {
|
|
352
|
+
Bucket: 'sandbox-tango-client',
|
|
353
|
+
Key: `${req.params.id}/documents/`,
|
|
354
|
+
fileName: `panCertificate.${req.files.panDoc.name.split( '.' )[1]}`,
|
|
355
|
+
ContentType: req.files.panDoc.mimetype,
|
|
356
|
+
body: req.files.panDoc.data,
|
|
357
|
+
};
|
|
358
|
+
await fileUpload( uploadDataParams );
|
|
359
|
+
}
|
|
360
|
+
if ( req.files?.cinDoc ) {
|
|
361
|
+
const uploadDataParams = {
|
|
362
|
+
Bucket: 'sandbox-tango-client',
|
|
363
|
+
Key: `${req.params.id}/documents/`,
|
|
364
|
+
fileName: `cinCertificate.${req.files.cinDoc.name.split( '.' )[1]}`,
|
|
365
|
+
ContentType: req.files.cinDoc.mimetype,
|
|
366
|
+
body: req.files.cinDoc.data,
|
|
367
|
+
};
|
|
368
|
+
await fileUpload( uploadDataParams );
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const updateAck = await documentsUpdate( {
|
|
372
|
+
clientId: req.params?.id, gstNumber: req.body.gstNumber, panNumber: req.body.panNumber, cinNumber: req.body.cinNumber,
|
|
373
|
+
addressDoc: req.files?.addressDoc ? `addressCertificate.${req.files?.addressDoc.name.split( '.' )[1]}` : undefined,
|
|
374
|
+
gstDoc: req.files?.gstDoc ? `gstCertificate.${req.files?.gstDoc.name.split( '.' )[1]}` : undefined,
|
|
375
|
+
panDoc: req.files?.panDoc ? `panCertificate.${req.files?.panDoc.name.split( '.' )[1]}` : undefined,
|
|
376
|
+
cinDoc: req.files?.cinDoc ? `cinCertificate.${req.files?.cinDoc.name.split( '.' )[1]}` : undefined,
|
|
377
|
+
|
|
378
|
+
} );
|
|
379
|
+
if ( updateAck ) {
|
|
380
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
381
|
+
}
|
|
382
|
+
} catch ( error ) {
|
|
383
|
+
logger.error( { error: error, message: req.params, function: 'updateBillingDetails' } );
|
|
384
|
+
return res.sendError( error, 500 );
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export async function getAuditConfiguration( req, res ) {
|
|
389
|
+
try {
|
|
390
|
+
const auditConfig = await auditConfigurationGet( { storeId: req.params?.id } );
|
|
391
|
+
if ( auditConfig ) {
|
|
392
|
+
const isDocExist = await checkFileExist( { Bucket: `sandbox-tango-client`, Key: `templates/audit_bulk_update.xlsx` } );
|
|
393
|
+
if ( isDocExist ) {
|
|
394
|
+
const signedFilUrl = await signedUrl( { Bucket: 'sandbox-tango-client', file_path: `templates/audit_bulk_update.xlsx` } );
|
|
395
|
+
auditConfig._doc.templateUrl = signedFilUrl;
|
|
396
|
+
} else {
|
|
397
|
+
auditConfig._doc.templateUrl = '';
|
|
398
|
+
}
|
|
399
|
+
res.sendSuccess( auditConfig );
|
|
400
|
+
} else {
|
|
401
|
+
res.sendError( { error: 'Store not found' }, 404 );
|
|
402
|
+
}
|
|
403
|
+
} catch ( error ) {
|
|
404
|
+
logger.error( { error: error, message: req.params, function: 'getAuditConfiguration' } );
|
|
405
|
+
return res.sendError( error, 500 );
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
export async function auditConfiguration( req, res ) {
|
|
411
|
+
try {
|
|
412
|
+
for ( let i = 0; i < req.body?.length; i++ ) {
|
|
413
|
+
await auditConfigurationUpdate( {
|
|
414
|
+
storeId: req.body[i].storeId,
|
|
415
|
+
count: req.body[i].count,
|
|
416
|
+
iteration: req.body[i].iteration,
|
|
417
|
+
ratio: normalizeNumber( req.body[i].ratio, 0, 100 ),
|
|
418
|
+
} );
|
|
419
|
+
}
|
|
420
|
+
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
421
|
+
} catch ( error ) {
|
|
422
|
+
logger.error( { error: error, message: req.params, function: 'auditConfiguration' } );
|
|
423
|
+
return res.sendError( error, 500 );
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function normalizeNumber( num, min, max ) {
|
|
428
|
+
return ( ( num - min ) / ( max - min ) ).toFixed( 2 );
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export async function getCsmUsers( req, res ) {
|
|
432
|
+
try {
|
|
433
|
+
const users = await CsmUsersGet();
|
|
434
|
+
if ( users?.length ) {
|
|
435
|
+
res.sendSuccess( users );
|
|
436
|
+
} else {
|
|
437
|
+
res.sendError( 'No users found', 404 );
|
|
438
|
+
}
|
|
439
|
+
} catch ( error ) {
|
|
440
|
+
logger.error( { error: error, message: req.params, function: 'getAuditConfiguration' } );
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
export async function clientList( req, res ) {
|
|
444
|
+
try {
|
|
445
|
+
const inputData = req.body;
|
|
446
|
+
let clientQuery = [];
|
|
447
|
+
const limit =inputData.limit || 10;
|
|
448
|
+
const skip = inputData.offset? ( inputData.offset - 1 ) * limit : 0;
|
|
449
|
+
if ( inputData.filterByPaymentStatus ) {
|
|
450
|
+
clientQuery.push(
|
|
451
|
+
{
|
|
452
|
+
$match: {
|
|
453
|
+
'planDetails.paymentStatus': { $in: inputData.filterByPaymentStatus },
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
if ( inputData.filterBySubscription ) {
|
|
459
|
+
clientQuery.push(
|
|
460
|
+
{
|
|
461
|
+
$match: {
|
|
462
|
+
'planDetails.subscriptionType': { $in: inputData.filterBySubscription },
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
if ( inputData.filterByStatus ) {
|
|
468
|
+
clientQuery.push(
|
|
469
|
+
{
|
|
470
|
+
$match: {
|
|
471
|
+
status: { $in: inputData.filterByStatus },
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
clientQuery.push(
|
|
478
|
+
{
|
|
479
|
+
$project: {
|
|
480
|
+
status: 1,
|
|
481
|
+
clientName: 1,
|
|
482
|
+
clientId: 1,
|
|
483
|
+
subscriptionType: '$planDetails.subscriptionType',
|
|
484
|
+
paymentStatus: '$planDetails.paymentStatus',
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
if ( inputData.searchValue ) {
|
|
490
|
+
clientQuery.push( {
|
|
491
|
+
$match: {
|
|
492
|
+
$or: [
|
|
493
|
+
{ clientId: { $regex: inputData.searchValue, $options: 'i' } },
|
|
494
|
+
{ clientName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
495
|
+
{ subscriptionType: { $regex: inputData.searchValue, $options: 'i' } },
|
|
496
|
+
{ status: { $regex: inputData.searchValue, $options: 'i' } },
|
|
497
|
+
],
|
|
498
|
+
|
|
499
|
+
},
|
|
500
|
+
} );
|
|
501
|
+
}
|
|
502
|
+
const clientCount = await aggregateClient( clientQuery );
|
|
503
|
+
if ( clientCount.length == 0 ) {
|
|
504
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if ( inputData.sortColumName ) {
|
|
508
|
+
clientQuery.push( {
|
|
509
|
+
$sort: { [inputData.sortColumName]: inputData.sortBy || -1 },
|
|
510
|
+
} );
|
|
511
|
+
}
|
|
512
|
+
if ( inputData.isExport ) {
|
|
513
|
+
clientQuery.push( {
|
|
514
|
+
$limit: 10000,
|
|
515
|
+
} );
|
|
516
|
+
} else {
|
|
517
|
+
clientQuery.push(
|
|
518
|
+
{ $skip: skip },
|
|
519
|
+
{ $limit: limit },
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
const client = await aggregateClient( clientQuery );
|
|
523
|
+
const clientListChunk = await chunkArray( client, 10 );
|
|
524
|
+
const promises = clientListChunk.map( async ( chunk ) => {
|
|
525
|
+
const list = [];
|
|
526
|
+
for ( let i = 0; i< chunk.length; i++ ) {
|
|
527
|
+
list.push( chunk[i].clientId );
|
|
528
|
+
}
|
|
529
|
+
return list;
|
|
530
|
+
} );
|
|
531
|
+
const clientList = await Promise.all( promises );
|
|
532
|
+
clientList.flat();
|
|
533
|
+
const storeQuery =[
|
|
534
|
+
{
|
|
535
|
+
$match: {
|
|
536
|
+
$and: [
|
|
537
|
+
{ status: { $eq: 'active' } },
|
|
538
|
+
{ clientId: { $in: clientList } },
|
|
539
|
+
],
|
|
540
|
+
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
$group: {
|
|
545
|
+
_id: '$clientId',
|
|
546
|
+
clientId: { $first: '$clientId' },
|
|
547
|
+
activeStoreCount: { $sum: 1 },
|
|
548
|
+
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
];
|
|
552
|
+
|
|
553
|
+
const cameraQuery =[
|
|
554
|
+
{
|
|
555
|
+
$match: {
|
|
556
|
+
$and: [
|
|
557
|
+
{ isActivated: { $eq: true } },
|
|
558
|
+
{ isUp: { $eq: true } },
|
|
559
|
+
{ clientId: { $in: clientList } },
|
|
560
|
+
],
|
|
561
|
+
},
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
$group: {
|
|
565
|
+
_id: '$clientId',
|
|
566
|
+
clientId: { $first: '$clientId' },
|
|
567
|
+
activeCameraCount: { $sum: 1 },
|
|
568
|
+
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
];
|
|
572
|
+
|
|
573
|
+
const activeStoreCount = await aggregateStore( storeQuery );
|
|
574
|
+
const activeCameraCount = await aggregateCamera( cameraQuery );
|
|
575
|
+
const result =_.values(
|
|
576
|
+
_.merge(
|
|
577
|
+
_.keyBy( client, 'clientId' ),
|
|
578
|
+
_.keyBy( activeStoreCount, 'clientId' ),
|
|
579
|
+
_.keyBy( activeCameraCount, 'clientId' ),
|
|
580
|
+
),
|
|
581
|
+
);
|
|
582
|
+
if ( inputData.isExport ) {
|
|
583
|
+
const resultChunk = await chunkArray( result, 10 );
|
|
584
|
+
const promises = resultChunk.map( async ( chunk ) => {
|
|
585
|
+
const list = [];
|
|
586
|
+
for ( let i = 0; i< chunk.length; i++ ) {
|
|
587
|
+
list.push( {
|
|
588
|
+
'client Name': chunk[i].clientName,
|
|
589
|
+
'client Id': chunk[i].clientId,
|
|
590
|
+
'Active Store': chunk[i].activeStoreCount,
|
|
591
|
+
'Active Camera': chunk[i].activeCameraCount,
|
|
592
|
+
'Payment Status': chunk[i].paymentStatus,
|
|
593
|
+
'Subs Plan': chunk[i].subscriptionType,
|
|
594
|
+
'Status': chunk[i].status,
|
|
595
|
+
} );
|
|
596
|
+
}
|
|
597
|
+
return list;
|
|
598
|
+
} );
|
|
599
|
+
const exportResult = await Promise.all( promises );
|
|
600
|
+
exportResult.flat();
|
|
601
|
+
await download( exportResult, res );
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
return res.sendSuccess( { result: result, count: clientCount.length } );
|
|
605
|
+
} catch ( error ) {
|
|
606
|
+
logger.error( { error: error, function: 'clientList' } );
|
|
607
|
+
return res.sendError( error, 500 );
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
export async function getOpsUsers( req, res ) {
|
|
612
|
+
try {
|
|
613
|
+
const users = await OpsUsersGet();
|
|
614
|
+
if ( users?.length ) {
|
|
615
|
+
res.sendSuccess( users );
|
|
616
|
+
} else {
|
|
617
|
+
res.sendError( 'No users found', 404 );
|
|
618
|
+
}
|
|
619
|
+
} catch ( error ) {
|
|
620
|
+
logger.error( { error: error, message: req.params, function: 'getOpsUsers' } );
|
|
621
|
+
return res.sendError( error, 500 );
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
export async function detailedClientCount( req, res ) {
|
|
627
|
+
try {
|
|
628
|
+
const inputData = req.query;
|
|
629
|
+
let result = {
|
|
630
|
+
clientName: inputData.clientName,
|
|
631
|
+
role: 'admin',
|
|
632
|
+
};
|
|
633
|
+
result['totalStoreCount'] = await countDocumentsStore( { clientId: inputData.clientId } );
|
|
634
|
+
result['totalGroupCount'] = await countDocumentsStore( { clientId: inputData.clientId } );
|
|
635
|
+
result['totalCameraCount'] = await countDocumentsCamera( { clientId: inputData.clientId } );
|
|
636
|
+
result['totalUserCount'] = await countDocumentsUser( { clientId: inputData.clientId, userType: 'client' } );
|
|
637
|
+
|
|
638
|
+
const user = await findOneUser( { _id: inputData.userId }, { userName: 1, email: 1 } );
|
|
639
|
+
result['userName'] = user?.userName;
|
|
640
|
+
result['email'] = user?.email;
|
|
641
|
+
result['profileCompletion'] = 70;
|
|
642
|
+
|
|
643
|
+
return res.sendSuccess( { result: result } );
|
|
644
|
+
} catch ( error ) {
|
|
645
|
+
logger.error( { error: error, function: 'detailedClientCount' } );
|
|
646
|
+
return res.sendError( error, 500 );
|
|
647
|
+
}
|
|
648
|
+
}
|