tango-app-api-audio-analytics 1.0.0

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.
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Cohort Controller
3
+ * Handles cohort creation and management endpoints
4
+ */
5
+
6
+ import {
7
+ createCohort as createCohortService,
8
+ getCohortById,
9
+ getCohortsByClientId,
10
+ updateCohort as updateCohortService,
11
+ deleteCohort as deleteCohortService,
12
+ searchCohorts,
13
+ getCohortAnalytics,
14
+ cohortExists,
15
+ } from '../services/cohort.service.js';
16
+ import {
17
+ cohortCreationSchema,
18
+ cohortUpdateSchema,
19
+ cohortQuerySchema,
20
+ validateCohortData,
21
+ } from '../validations/cohort.validation.js';
22
+ import { logger } from 'tango-app-api-middleware';
23
+
24
+ /**
25
+ * Create new cohort
26
+ * POST /cohorts
27
+ *
28
+ * @param {Object} req - Express request object
29
+ * @param {Object} res - Express response object
30
+ */
31
+ export const createCohort = async ( req, res ) => {
32
+ try {
33
+ logger.info( 'Creating new cohort' );
34
+
35
+ const { error, value: validatedData } = await validateCohortData(
36
+ req.body,
37
+ cohortCreationSchema,
38
+ );
39
+
40
+ if ( error ) {
41
+ logger.warn( 'Cohort validation failed', error );
42
+ return res.status( 400 ).json( {
43
+ status: 'error',
44
+ message: error.message,
45
+ code: 'VALIDATION_ERROR',
46
+ details: error.details,
47
+ timestamp: new Date().toISOString(),
48
+ } );
49
+ }
50
+
51
+ // Check if cohort already exists
52
+ const exists = await cohortExists( validatedData.cohortId );
53
+ if ( exists ) {
54
+ logger.warn( `Cohort already exists: ${validatedData.cohortId}` );
55
+ return res.status( 409 ).json( {
56
+ status: 'error',
57
+ message: 'Cohort with this ID already exists',
58
+ code: 'COHORT_EXISTS',
59
+ timestamp: new Date().toISOString(),
60
+ } );
61
+ }
62
+
63
+ // Create cohort in OpenSearch
64
+ const result = await createCohortService( validatedData );
65
+
66
+ logger.info( 'Cohort created successfully', {
67
+ cohortId: validatedData.cohortId,
68
+ documentId: result.data.documentId,
69
+ } );
70
+
71
+ res.status( 201 ).json( {
72
+ status: 'success',
73
+ message: result.message,
74
+ data: {
75
+ cohortId: result.data.cohortId,
76
+ cohortName: result.data.cohortName,
77
+ clientId: result.data.clientId,
78
+ documentId: result.data.documentId,
79
+ createdAt: result.data.createdAt,
80
+ metricsCount: result.data.metrics.length,
81
+ },
82
+ timestamp: new Date().toISOString(),
83
+ } );
84
+ } catch ( error ) {
85
+ logger.error( `Error creating cohort: ${error.message}`, error );
86
+
87
+ if ( error.code === 'COHORT_CREATE_ERROR' ) {
88
+ return res.status( 500 ).json( {
89
+ status: 'error',
90
+ message: error.message,
91
+ code: error.code,
92
+ timestamp: new Date().toISOString(),
93
+ } );
94
+ }
95
+
96
+ res.status( 500 ).json( {
97
+ status: 'error',
98
+ message: 'Internal server error',
99
+ code: 'INTERNAL_ERROR',
100
+ timestamp: new Date().toISOString(),
101
+ } );
102
+ }
103
+ };
104
+
105
+ /**
106
+ * Get cohort by ID
107
+ * GET /cohorts/:cohortId
108
+ *
109
+ * @param {Object} req - Express request object
110
+ * @param {Object} res - Express response object
111
+ */
112
+ export const getCohort = async ( req, res ) => {
113
+ try {
114
+ const { cohortId } = req.params;
115
+
116
+ logger.info( `Fetching cohort: ${cohortId}` );
117
+
118
+ const cohort = await getCohortById( cohortId );
119
+
120
+ res.status( 200 ).json( {
121
+ status: 'success',
122
+ data: cohort,
123
+ timestamp: new Date().toISOString(),
124
+ } );
125
+ } catch ( error ) {
126
+ logger.error( `Error fetching cohort: ${error.message}`, error );
127
+
128
+ if ( error.message.includes( 'not found' ) ) {
129
+ return res.status( 404 ).json( {
130
+ status: 'error',
131
+ message: 'Cohort not found',
132
+ code: 'COHORT_NOT_FOUND',
133
+ timestamp: new Date().toISOString(),
134
+ } );
135
+ }
136
+
137
+ res.status( 500 ).json( {
138
+ status: 'error',
139
+ message: 'Internal server error',
140
+ code: 'INTERNAL_ERROR',
141
+ timestamp: new Date().toISOString(),
142
+ } );
143
+ }
144
+ };
145
+
146
+ /**
147
+ * Get cohorts by client ID
148
+ * GET /cohorts/client/:clientId
149
+ *
150
+ * @param {Object} req - Express request object
151
+ * @param {Object} res - Express response object
152
+ */
153
+ export const getCohortsByClient = async ( req, res ) => {
154
+ try {
155
+ const { clientId } = req.params;
156
+ const { limit = 10, offset = 0 } = req.query;
157
+
158
+ logger.info( `Fetching cohorts for client: ${clientId}` );
159
+
160
+ const result = await getCohortsByClientId(
161
+ clientId,
162
+ parseInt( limit ),
163
+ parseInt( offset ),
164
+ );
165
+
166
+ res.status( 200 ).json( {
167
+ status: 'success',
168
+ data: result.cohorts,
169
+ pagination: result.pagination,
170
+ timestamp: new Date().toISOString(),
171
+ } );
172
+ } catch ( error ) {
173
+ logger.error( `Error fetching cohorts: ${error.message}`, error );
174
+
175
+ res.status( 500 ).json( {
176
+ status: 'error',
177
+ message: 'Internal server error',
178
+ code: 'INTERNAL_ERROR',
179
+ timestamp: new Date().toISOString(),
180
+ } );
181
+ }
182
+ };
183
+
184
+ /**
185
+ * Search cohorts
186
+ * POST /cohorts/search
187
+ *
188
+ * @param {Object} req - Express request object
189
+ * @param {Object} res - Express response object
190
+ */
191
+ export const searchCohortsEndpoint = async ( req, res ) => {
192
+ try {
193
+ const { error, value: validatedData } = await validateCohortData(
194
+ req.body,
195
+ cohortQuerySchema,
196
+ );
197
+
198
+ if ( error ) {
199
+ return res.status( 400 ).json( {
200
+ status: 'error',
201
+ message: error.message,
202
+ code: 'VALIDATION_ERROR',
203
+ details: error.details,
204
+ timestamp: new Date().toISOString(),
205
+ } );
206
+ }
207
+
208
+ logger.info( 'Searching cohorts' );
209
+
210
+ const result = await searchCohorts(
211
+ {
212
+ clientId: validatedData.clientId,
213
+ cohortId: validatedData.cohortId,
214
+ cohortName: validatedData.cohortName,
215
+ },
216
+ validatedData.limit,
217
+ validatedData.offset,
218
+ );
219
+
220
+ res.status( 200 ).json( {
221
+ status: 'success',
222
+ data: result.cohorts,
223
+ pagination: result.pagination,
224
+ timestamp: new Date().toISOString(),
225
+ } );
226
+ } catch ( error ) {
227
+ logger.error( `Error searching cohorts: ${error.message}`, error );
228
+
229
+ res.status( 500 ).json( {
230
+ status: 'error',
231
+ message: 'Internal server error',
232
+ code: 'INTERNAL_ERROR',
233
+ timestamp: new Date().toISOString(),
234
+ } );
235
+ }
236
+ };
237
+
238
+ /**
239
+ * Update cohort
240
+ * PUT /cohorts/:documentId
241
+ *
242
+ * @param {Object} req - Express request object
243
+ * @param {Object} res - Express response object
244
+ */
245
+ export const updateCohort = async ( req, res ) => {
246
+ try {
247
+ const { documentId } = req.params;
248
+
249
+ const { error, value: validatedData } = await validateCohortData(
250
+ req.body,
251
+ cohortUpdateSchema,
252
+ );
253
+
254
+ if ( error ) {
255
+ return res.status( 400 ).json( {
256
+ status: 'error',
257
+ message: error.message,
258
+ code: 'VALIDATION_ERROR',
259
+ details: error.details,
260
+ timestamp: new Date().toISOString(),
261
+ } );
262
+ }
263
+
264
+ logger.info( `Updating cohort: ${documentId}` );
265
+
266
+ const result = await updateCohortService( documentId, validatedData );
267
+
268
+ res.status( 200 ).json( {
269
+ status: 'success',
270
+ message: result.message,
271
+ data: result.data,
272
+ timestamp: new Date().toISOString(),
273
+ } );
274
+ } catch ( error ) {
275
+ logger.error( `Error updating cohort: ${error.message}`, error );
276
+
277
+ res.status( 500 ).json( {
278
+ status: 'error',
279
+ message: 'Internal server error',
280
+ code: 'INTERNAL_ERROR',
281
+ timestamp: new Date().toISOString(),
282
+ } );
283
+ }
284
+ };
285
+
286
+ /**
287
+ * Delete cohort
288
+ * DELETE /cohorts/:documentId
289
+ *
290
+ * @param {Object} req - Express request object
291
+ * @param {Object} res - Express response object
292
+ */
293
+ export const deleteCohort = async ( req, res ) => {
294
+ try {
295
+ const { documentId } = req.params;
296
+
297
+ logger.info( `Deleting cohort: ${documentId}` );
298
+
299
+ const result = await deleteCohortService( documentId );
300
+
301
+ res.status( 200 ).json( {
302
+ status: 'success',
303
+ message: result.message,
304
+ timestamp: new Date().toISOString(),
305
+ } );
306
+ } catch ( error ) {
307
+ logger.error( `Error deleting cohort: ${error.message}`, error );
308
+
309
+ res.status( 500 ).json( {
310
+ status: 'error',
311
+ message: 'Internal server error',
312
+ code: 'INTERNAL_ERROR',
313
+ timestamp: new Date().toISOString(),
314
+ } );
315
+ }
316
+ };
317
+
318
+ /**
319
+ * Get cohort analytics
320
+ * GET /cohorts/:cohortId/analytics
321
+ *
322
+ * @param {Object} req - Express request object
323
+ * @param {Object} res - Express response object
324
+ */
325
+ export const getCohortAnalyticsEndpoint = async ( req, res ) => {
326
+ try {
327
+ const { cohortId } = req.params;
328
+
329
+ logger.info( `Fetching analytics for cohort: ${cohortId}` );
330
+
331
+ const analytics = await getCohortAnalytics( cohortId );
332
+
333
+ res.status( 200 ).json( {
334
+ status: 'success',
335
+ data: analytics,
336
+ timestamp: new Date().toISOString(),
337
+ } );
338
+ } catch ( error ) {
339
+ logger.error( `Error fetching cohort analytics: ${error.message}`, error );
340
+
341
+ if ( error.message.includes( 'not found' ) ) {
342
+ return res.status( 404 ).json( {
343
+ status: 'error',
344
+ message: 'Cohort not found',
345
+ code: 'COHORT_NOT_FOUND',
346
+ timestamp: new Date().toISOString(),
347
+ } );
348
+ }
349
+
350
+ res.status( 500 ).json( {
351
+ status: 'error',
352
+ message: 'Internal server error',
353
+ code: 'INTERNAL_ERROR',
354
+ timestamp: new Date().toISOString(),
355
+ } );
356
+ }
357
+ };
@@ -0,0 +1,46 @@
1
+ // import { sampleCohortData } from '../models/cohortAnalysis.model.js';
2
+ import { logger } from 'tango-app-api-middleware';
3
+
4
+ /**
5
+ * Get Complete Cohort Analysis
6
+ * GET /cohort-analysis
7
+ * @param {Object} req - Express request object
8
+ * @param {Object} req.body - Request body with analysis parameters
9
+ * @param {string} req.body.startDate - Start date for analysis
10
+ * @param {string} req.body.endDate - End date for analysis
11
+ * @param {string} req.body.storeId - Store ID for filtering
12
+ * @param {Object} res - Express response object
13
+ * @return {void} Returns JSON response with cohort analysis data
14
+ */
15
+ export const getCohortAnalysis = async ( req, res ) => {
16
+ try {
17
+ const { startDate, endDate, storeId } = req.body;
18
+
19
+ // Validation
20
+ if ( !startDate || !endDate || !storeId ) {
21
+ return res.status( 400 ).json( {
22
+ status: 'error',
23
+ message: 'Missing required parameters: startDate, endDate, storeId',
24
+ code: 'MISSING_PARAMETERS',
25
+ timestamp: new Date().toISOString(),
26
+ } );
27
+ }
28
+
29
+ logger.info( `Fetching cohort analysis for store ${storeId} from ${startDate} to ${endDate}` );
30
+
31
+ // Return sample data (replace with database query later)
32
+ return res.status( 200 ).json( {
33
+ status: 'success',
34
+ data: 'sampleCohortData',
35
+ timestamp: new Date().toISOString(),
36
+ } );
37
+ } catch ( error ) {
38
+ logger.error( `Error fetching cohort analysis: ${error.message}` );
39
+ return res.status( 500 ).json( {
40
+ status: 'error',
41
+ message: 'Internal server error',
42
+ code: 'INTERNAL_ERROR',
43
+ timestamp: new Date().toISOString(),
44
+ } );
45
+ }
46
+ };
@@ -0,0 +1,92 @@
1
+ // import { sampleConversationData, sampleConversationsList } from '../models/conversationAnalysis.model.js';
2
+ import { logger } from 'tango-app-api-middleware';
3
+
4
+ /**
5
+ * Get Conversation Analysis List
6
+ * POST /conversations/list
7
+ * @param {Object} req - Express request object
8
+ * @param {Object} req.body - Request body with query parameters
9
+ * @param {string} req.body.startDate - Start date for filtering
10
+ * @param {string} req.body.endDate - End date for filtering
11
+ * @param {string} req.body.storeId - Store ID for filtering
12
+ * @param {Object} res - Express response object
13
+ * @return {void} Returns JSON response with conversations list
14
+ */
15
+ export const getConversationsList = async ( req, res ) => {
16
+ try {
17
+ const { startDate, endDate, storeId } = req.body;
18
+
19
+ // Validation
20
+ if ( !startDate || !endDate || !storeId ) {
21
+ return res.status( 400 ).json( {
22
+ status: 'error',
23
+ message: 'Missing required parameters: startDate, endDate, storeId',
24
+ code: 'MISSING_PARAMETERS',
25
+ timestamp: new Date().toISOString(),
26
+ } );
27
+ }
28
+
29
+ logger.info( `Fetching conversations for store ${storeId} from ${startDate} to ${endDate}` );
30
+
31
+ return res.status( 200 ).json( {
32
+ status: 'success',
33
+ data: {
34
+ totalConversations: 0,
35
+ conversations: 'sampleConversationsList',
36
+ },
37
+ timestamp: new Date().toISOString(),
38
+ } );
39
+ } catch ( error ) {
40
+ logger.error( `Error fetching conversations: ${error.message}` );
41
+ return res.status( 500 ).json( {
42
+ status: 'error',
43
+ message: 'Internal server error',
44
+ code: 'INTERNAL_ERROR',
45
+ timestamp: new Date().toISOString(),
46
+ } );
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Get Single Conversation Details
52
+ * POST /conversations/:conversationId
53
+ * @param {Object} req - Express request object
54
+ * @param {Object} req.params - URL parameters
55
+ * @param {string} req.params.conversationId - Conversation ID from URL
56
+ * @param {Object} req.body - Request body with store information
57
+ * @param {string} req.body.storeId - Store ID for filtering
58
+ * @param {Object} res - Express response object
59
+ * @return {void} Returns JSON response with conversation details
60
+ */
61
+ export const getConversationDetails = async ( req, res ) => {
62
+ try {
63
+ const { conversationId } = req.params;
64
+ const { storeId } = req.body;
65
+
66
+ if ( !conversationId || !storeId ) {
67
+ return res.status( 400 ).json( {
68
+ status: 'error',
69
+ message: 'Missing required parameters',
70
+ code: 'MISSING_PARAMETERS',
71
+ timestamp: new Date().toISOString(),
72
+ } );
73
+ }
74
+
75
+ logger.info( `Fetching conversation ${conversationId}` );
76
+
77
+ return res.status( 200 ).json( {
78
+ status: 'success',
79
+ data: 'sampleConversationData',
80
+ timestamp: new Date().toISOString(),
81
+ } );
82
+ } catch ( error ) {
83
+ logger.error( `Error fetching conversation: ${error.message}` );
84
+ return res.status( 500 ).json( {
85
+ status: 'error',
86
+ message: 'Internal server error',
87
+ code: 'INTERNAL_ERROR',
88
+ timestamp: new Date().toISOString(),
89
+ } );
90
+ }
91
+ };
92
+