tango-app-api-task 1.0.0-alpha.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.
package/.eslintrc.cjs ADDED
@@ -0,0 +1,41 @@
1
+
2
+ module.exports = {
3
+ 'env': {
4
+ 'es2021': true,
5
+ 'node': true,
6
+ },
7
+ 'extends': 'google',
8
+ 'overrides': [
9
+ {
10
+ 'env': {
11
+ 'node': true,
12
+ },
13
+ 'files': [
14
+ '.eslintrc.{js,cjs}',
15
+ ],
16
+ 'parserOptions': {
17
+ 'sourceType': 'script',
18
+ },
19
+ },
20
+ ],
21
+ 'parserOptions': {
22
+ 'ecmaVersion': 'latest',
23
+ 'sourceType': 'module',
24
+ },
25
+ 'rules': {
26
+ 'linebreak-style': [ 'error', 'windows' ],
27
+ 'require-jsdoc': 'off',
28
+ 'arrow-spacing': 'error',
29
+ 'key-spacing': [ 'error', { 'beforeColon': false, 'afterColon': true } ],
30
+ 'object-curly-spacing': [ 'error', 'always' ],
31
+ 'space-in-parens': [ 'error', 'always' ],
32
+ 'keyword-spacing': 'error',
33
+ 'array-bracket-spacing': [ 'error', 'always' ],
34
+ 'spaced-comment': [ 'error', 'always' ],
35
+ 'max-len': [ 'error', { 'code': 700 } ],
36
+ 'no-unused-vars': 'error',
37
+ 'new-cap': [ 'error', { 'newIsCap': true, 'capIsNew': false } ],
38
+ 'prefer-const': 'off',
39
+ },
40
+ };
41
+
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # README #
2
+
3
+ This README would normally document whatever steps are necessary to get your application up and running.
4
+
5
+ ### What is this repository for? ###
6
+
7
+ * Quick summary
8
+ * Version
9
+ * [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
10
+
11
+ ### How do I get set up? ###
12
+
13
+ * Summary of set up
14
+ * Configuration
15
+ * Dependencies
16
+ * Database configuration
17
+ * How to run tests
18
+ * Deployment instructions
19
+
20
+ ### Contribution guidelines ###
21
+
22
+ * Writing tests
23
+ * Code review
24
+ * Other guidelines
25
+
26
+ ### Who do I talk to? ###
27
+
28
+ * Repo owner or admin
29
+ * Other community or team contact
package/index.js ADDED
@@ -0,0 +1,10 @@
1
+
2
+
3
+ import { taskRouter } from './src/routes/task.routes.js';
4
+ import { internalAPIRouter } from './src/routes/internalAPI.routes.js';
5
+ import { taskDashboardRouter } from './src/routes/taskDashboard.routes.js';
6
+ import { taskActionCenterRouter } from './src/routes/taskActionCenter.routes.js';
7
+
8
+ export { taskRouter, internalAPIRouter, taskDashboardRouter, taskActionCenterRouter };
9
+
10
+
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "tango-app-api-task",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "Task",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "start": "nodemon --exec \"eslint --fix . && node index.js\""
9
+ },
10
+ "engines": {
11
+ "node": ">=18.10.0"
12
+ },
13
+ "author": "praveenraj",
14
+ "license": "ISC",
15
+ "dependencies": {
16
+ "aws-sdk": "^2.1692.0",
17
+ "body-parser": "^1.20.3",
18
+ "cors": "^2.8.5",
19
+ "dayjs": "^1.11.13",
20
+ "dotenv": "^16.4.5",
21
+ "express": "^4.21.1",
22
+ "express-fileupload": "^1.5.1",
23
+ "handlebars": "^4.7.8",
24
+ "mongodb": "^6.10.0",
25
+ "nodemon": "^3.1.7",
26
+ "tango-api-schema": "^2.1.86",
27
+ "tango-app-api-middleware": "^3.1.43-alpha.9",
28
+ "winston": "^3.17.0",
29
+ "winston-daily-rotate-file": "^5.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "eslint": "^8.57.1",
33
+ "eslint-config-google": "^0.14.0",
34
+ "eslint-config-semistandard": "^17.0.0",
35
+ "eslint-config-standard": "^17.1.0",
36
+ "eslint-plugin-import": "^2.31.0",
37
+ "eslint-plugin-promise": "^6.6.0"
38
+ }
39
+ }
@@ -0,0 +1,304 @@
1
+ import dayjs from 'dayjs';
2
+ import customParseFormat from 'dayjs/plugin/customParseFormat.js';
3
+ import timeZone from 'dayjs/plugin/timezone.js';
4
+ import utc from 'dayjs/plugin/utc.js';
5
+ import * as taskService from '../service/task.service.js';
6
+ import * as taskQuestionService from '../service/taskQuestion.service.js';
7
+ import * as taskAssignService from '../service/taskAssign.service.js';
8
+ import * as taskProcessedConfigService from '../service/processedTaskConfig.service.js';
9
+ import * as taskProcessedService from '../service/processedTaskList.service.js';
10
+ import { logger } from 'tango-app-api-middleware';
11
+ import mongoose from 'mongoose';
12
+ const ObjectId = mongoose.Types.ObjectId;
13
+ dayjs.extend( customParseFormat );
14
+ dayjs.extend( utc );
15
+ dayjs.extend( timeZone );
16
+
17
+ export async function PCLTaskCreationValidator( req, res, next ) {
18
+ try {
19
+ let requestData = req.body;
20
+ let validateError = [];
21
+ if (
22
+ !requestData.hasOwnProperty( 'date' ) ||
23
+ requestData.date === undefined ||
24
+ requestData.date === null ||
25
+ requestData.date == ''
26
+ ) {
27
+ validateError.push( 'Date Is Required' );
28
+ }
29
+
30
+ if ( !requestData.hasOwnProperty( 'client_id' ) ) {
31
+ validateError.push( 'client_id Is Required' );
32
+ }
33
+
34
+ if ( validateError.length > 0 ) {
35
+ return res.sendError( validateError + ',', 400 );
36
+ } else {
37
+ let dateList = [];
38
+ let date = dayjs();
39
+ let reqDate = dayjs( requestData.date );
40
+ let loopCount = parseInt( requestData.numberofDays ) || 1;
41
+ for ( let i = 1; i <= loopCount; i++ ) {
42
+ if ( reqDate > date || reqDate.format( 'YYYY-MM-DD' ) == date.format( 'YYYY-MM-DD' ) ) {
43
+ dateList.push( reqDate.format( 'YYYY-MM-DD' ) );
44
+ }
45
+ reqDate = reqDate.add( 1, 'days' );
46
+ }
47
+ req.body.date = dateList;
48
+ next();
49
+ }
50
+ } catch ( error ) {
51
+ logger.error( { function: 'PCLTaskCreationValidator', error: error } );
52
+ return res.sendError( error, 500 );
53
+ }
54
+ }
55
+
56
+ export async function PCLTaskconfigCreation( req, res ) {
57
+ try {
58
+ let requestData = req.body;
59
+ let dateList = [ ...requestData.date ];
60
+ requestData.date = [ requestData.date[0] ];
61
+ let response = await insertData( requestData );
62
+ if ( response.success == true ) {
63
+ dateList.splice( 0, 1 );
64
+ requestData.date = dateList;
65
+ if ( dateList.length ) {
66
+ insertData( requestData );
67
+ }
68
+ return res.sendSuccess( { message: 'Processed Daily Task Created Successfully', error: response.error } );
69
+ } else {
70
+ if ( response.error == 'no Content' ) {
71
+ if ( requestData.numberofDays == 1 || !requestData?.numberofDays ) {
72
+ return res.sendError( 'no data', 204 );
73
+ } else {
74
+ dateList.splice( 0, 1 );
75
+ requestData.date = dateList;
76
+ requestData.numberofDays = requestData.numberofDays -1;
77
+ req.body = requestData;
78
+ PCLTaskconfigCreation( req, res );
79
+ }
80
+ } else {
81
+ return res.sendSuccess( { message: response.error } );
82
+ }
83
+ }
84
+ } catch ( e ) {
85
+ logger.error( { function: 'PCLTaskconfigCreation', error: e } );
86
+ return res.sendError( e, 500 );
87
+ }
88
+ };
89
+
90
+ async function insertData( requestData ) {
91
+ for ( let [ dateIndex, date ] of requestData.date.entries() ) {
92
+ let currentdate = dayjs( date ).format( 'YYYY-MM-DD' );
93
+ let clientCount = 0;
94
+ let start = new Date( date );
95
+ let userTimezoneOffset = start.getTimezoneOffset() * 60000;
96
+ start = new Date( start.getTime() - userTimezoneOffset );
97
+ start.setUTCHours( 0, 0, 0, 0 );
98
+ let end = new Date( date );
99
+ end = new Date( end.getTime() - userTimezoneOffset );
100
+ end.setUTCHours( 23, 59, 59, 59 );
101
+ let alreadyExist = [];
102
+ for ( let [ clientlistIndex, clientlist ] of requestData.client_id.entries() ) {
103
+ let getuniquechecklistquery = [];
104
+ getuniquechecklistquery.push( {
105
+ $match: {
106
+ client_id: clientlist,
107
+ isdeleted: false,
108
+ publish: true,
109
+ },
110
+ } );
111
+ let getuniquechecklist = await taskService.aggregate( getuniquechecklistquery );
112
+ clientCount += getuniquechecklist.length;
113
+
114
+ if ( clientCount == 0 && clientlistIndex == requestData.client_id.length - 1 ) {
115
+ return { success: false, error: 'no Content' };
116
+ }
117
+
118
+ if ( getuniquechecklist.length ) {
119
+ let resultchecklist = [];
120
+
121
+ for ( let element1 of getuniquechecklist ) {
122
+ let endDate = dayjs( element1?.scheduleDate ).format( 'YYYY-MM-DD' ) + ' ' + element1.scheduleEndTime;
123
+ endDate = dayjs.utc( endDate, 'YYYY-MM-DD hh:mm A' ).format();
124
+ if ( endDate >= dayjs( date ).format() ) {
125
+ resultchecklist.push( element1._id );
126
+ }
127
+ }
128
+
129
+ console.log( resultchecklist );
130
+
131
+
132
+ if ( resultchecklist.length ) {
133
+ for ( let [ index2, element2 ] of resultchecklist.entries() ) {
134
+ let getCLconfig = await taskService.findOne( { _id: element2 } );
135
+ if ( getCLconfig ) {
136
+ if ( dayjs( getCLconfig?.scheduleDate ).format( 'YYYY-MM-DD' ) != dayjs( date ).format( 'YYYY-MM-DD' ) ) {
137
+ getCLconfig.scheduleEndTime = '11:59 PM';
138
+ }
139
+ console.log( getCLconfig.scheduleEndTime );
140
+
141
+ let startTimeIso; let endTimeIso;
142
+ startTimeIso = dayjs.utc( `${currentdate} 12:00 AM`, 'YYYY-MM-DD hh:mm A' );
143
+ endTimeIso = dayjs.utc( `${currentdate} ${getCLconfig.scheduleEndTime}`, 'YYYY-MM-DD hh:mm A' );
144
+ console.log( endTimeIso );
145
+
146
+ let insertdata = {};
147
+ insertdata.date_iso = startTimeIso.format();
148
+ insertdata.date_string = currentdate;
149
+ insertdata.sourceCheckList_id = getCLconfig._id;
150
+ insertdata.checkListName = getCLconfig.checkListName;
151
+ insertdata.publish = getCLconfig.publish;
152
+ insertdata.scheduleStartTime = startTimeIso.format();
153
+ insertdata.scheduleStartTime_iso = startTimeIso.format();
154
+ insertdata.scheduleEndTime = getCLconfig.scheduleEndTime;
155
+ insertdata.scheduleEndTime_iso = endTimeIso.format();
156
+ insertdata.allowedOverTime = false;
157
+ insertdata.allowedStoreLocation = getCLconfig.allowedStoreLocation;
158
+ insertdata.client_id = getCLconfig.client_id;
159
+ insertdata.createdBy = new ObjectId( getCLconfig.createdBy );
160
+ insertdata.createdByName = getCLconfig.createdByName;
161
+ insertdata.checkListType = getCLconfig.checkListType;
162
+ insertdata.storeCount = getCLconfig.storeCount;
163
+ insertdata.questionCount = getCLconfig.questionCount;
164
+ insertdata.publishDate = getCLconfig.publishDate;
165
+ insertdata.locationCount = getCLconfig.locationCount;
166
+ insertdata.scheduleRepeatedType = 'daily';
167
+ insertdata.allowedMultiSubmit = false;
168
+ insertdata.approver = getCLconfig.approver;
169
+ let collectSections = [];
170
+ let sectionQuery = [];
171
+ sectionQuery.push( {
172
+ $match: {
173
+ checkListId: element2,
174
+ isdeleted: false,
175
+ },
176
+ } );
177
+ let getSections = await taskQuestionService.aggregate( sectionQuery );
178
+ if ( getSections.length ) {
179
+ for ( let element3 of getSections ) {
180
+ let collectQuestions = {};
181
+ collectQuestions.section_id = element3._id;
182
+ collectQuestions.sectionName = element3.section;
183
+ collectQuestions.questions = element3.question;
184
+ collectSections.push( collectQuestions );
185
+ }
186
+ insertdata.questionAnswers = collectSections;
187
+ insertdata.updatedAt = new Date();
188
+ let insertdataquery = {};
189
+ insertdataquery.date_string = insertdata.date_string;
190
+ insertdataquery.date_iso = insertdata.date_iso;
191
+ insertdataquery.client_id = insertdata.client_id;
192
+ insertdataquery.sourceCheckList_id = insertdata.sourceCheckList_id;
193
+ insertdataquery.startTime = { $exists: true };
194
+ let checkchecklist = await taskProcessedConfigService.findOne( insertdataquery );
195
+ if ( !checkchecklist ) {
196
+ delete insertdataquery.startTime;
197
+ let updatedchecklist;
198
+ let checklistDetails = await taskProcessedConfigService.findOne( insertdataquery );
199
+ if ( !checklistDetails ) {
200
+ updatedchecklist = await taskProcessedConfigService.insert( insertdata );
201
+ } else {
202
+ await taskProcessedConfigService.updateOne( { _id: checklistDetails._id }, insertdata );
203
+ updatedchecklist = checklistDetails;
204
+ }
205
+ if ( updatedchecklist ) {
206
+ let getquestionQuery = [];
207
+ getquestionQuery.push( {
208
+ $match: {
209
+ checkListId: element2,
210
+ checkFlag: true,
211
+ isdeleted: false,
212
+ ...( getCLconfig?.reinitiate ) ? { reinitiate: true } : {},
213
+ },
214
+ } );
215
+ let allQuestion = await taskAssignService.aggregate( getquestionQuery );
216
+ if ( allQuestion.length ) {
217
+ let userIdList = [];
218
+ for ( let element4 of allQuestion ) {
219
+ let query= {
220
+ sourceCheckList_id: getCLconfig._id,
221
+ $or: [ {
222
+ checklistStatus: { $in: [ 'submit' ] } },
223
+ { submitTime: { $exists: true } },
224
+ ],
225
+ userId: element4.userId,
226
+ store_id: element4.store_id,
227
+ $and: [ {
228
+ date_iso: {
229
+ $lte: new Date( endTimeIso.format( 'YYYY-MM-DD' ) ) },
230
+ } ],
231
+
232
+ };
233
+
234
+ let getsubmitDetails = await taskProcessedService.find( query );
235
+ if ( getsubmitDetails.length ) {
236
+ userIdList.push( element4._id );
237
+ continue;
238
+ }
239
+
240
+ delete element4._id;
241
+ delete element4.checkFlag;
242
+ delete element4.isdeleted;
243
+ delete element4.createdAt;
244
+ delete element4.updatedAt;
245
+ element4.checkListId = updatedchecklist._id;
246
+ element4.checkListName = getCLconfig.checkListName;
247
+ element4.date_iso = new Date( currentdate );
248
+ element4.date_string = currentdate;
249
+ element4.allowedOverTime = false;
250
+ element4.allowedStoreLocation = getCLconfig.allowedStoreLocation;
251
+ element4.scheduleStartTime = startTimeIso.format();
252
+ element4.scheduleStartTime_iso = startTimeIso.format();
253
+ element4.scheduleEndTime = getCLconfig.scheduleEndTime;
254
+ element4.scheduleEndTime_iso = endTimeIso.format();
255
+ element4.createdBy = new ObjectId( getCLconfig.createdBy );
256
+ element4.createdByName = getCLconfig.createdByName;
257
+ element4.sourceCheckList_id = getCLconfig._id;
258
+ element4.checkListType = getCLconfig.checkListType;
259
+ element4.storeCount = getCLconfig.storeCount;
260
+ element4.questionCount = getCLconfig.questionCount;
261
+ element4.publishDate = getCLconfig.publishDate;
262
+ element4.locationCount = getCLconfig.locationCount;
263
+ element4.scheduleRepeatedType = 'daily';
264
+ element4.approvalEnable = getCLconfig.approver.length ? true : false;
265
+ }
266
+ if ( userIdList.length ) {
267
+ allQuestion = allQuestion.filter( ( item ) => typeof item._id == 'undefined' );
268
+ }
269
+ console.log( allQuestion );
270
+
271
+ if ( allQuestion ) {
272
+ let assigndeletequery = {};
273
+ assigndeletequery.date_string = insertdata.date_string;
274
+ assigndeletequery.date_iso = insertdata.date_iso;
275
+ assigndeletequery.client_id = insertdata.client_id;
276
+ assigndeletequery.checkListId = updatedchecklist._id;
277
+ assigndeletequery.checklistStatus = { $nin: [ 'submit' ] };
278
+ await taskProcessedService.deleteMany( assigndeletequery );
279
+ await taskProcessedService.insertMany( allQuestion );
280
+ logger.info( { function: 'taskProcessedCreation', query: assigndeletequery } );
281
+ }
282
+ }
283
+ }
284
+ } else {
285
+ alreadyExist.push( { sourceCheckList_id: insertdata.sourceCheckList_id, checkListName: insertdata.checkListName } );
286
+ }
287
+ }
288
+ }
289
+
290
+ if ( resultchecklist.length - 1 == index2 && requestData.client_id.length - 1 == clientlistIndex && dateIndex == requestData.date.length - 1 ) {
291
+ return { success: true, error: alreadyExist };
292
+ }
293
+ }
294
+ } else {
295
+ if ( requestData.date.length == 1 ) {
296
+ return { success: false, error: 'no Content' };
297
+ } else {
298
+ continue;
299
+ }
300
+ }
301
+ }
302
+ }
303
+ }
304
+ }