From ef29cd13a027efecea1174994565fec1eb3d6f94 Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Fri, 30 Jul 2021 11:36:37 +0530 Subject: [PATCH 001/373] Mongodb health check issue --- healthCheck/mongodb.js | 1 + 1 file changed, 1 insertion(+) diff --git a/healthCheck/mongodb.js b/healthCheck/mongodb.js index 96f7f2f9..3efc6288 100644 --- a/healthCheck/mongodb.js +++ b/healthCheck/mongodb.js @@ -20,6 +20,7 @@ function health_check() { return resolve(false) }); db.once("open", function() { + db.close(function(){}); return resolve(true); }); }) From 3db449b00254dce00ad839cafbb4500a6799ce94 Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Mon, 30 Aug 2021 10:51:32 +0530 Subject: [PATCH 002/373] Remove details validator --- module/userProjects/validator/v1.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index c0d63cd7..5405419c 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -20,9 +20,6 @@ module.exports = (req) => { req.checkParams('_id').exists().withMessage("required project id"); req.checkQuery('lastDownloadedAt').exists().withMessage("required last downloaded at"); }, - details : function () { - req.checkParams('_id').exists().withMessage("required project id"); - }, tasksStatus : function () { req.checkParams('_id').exists().withMessage("required project id"); }, From 0490deda6c3d10ba12321c3c8350de69c1c85b0f Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 30 Aug 2021 11:46:52 +0530 Subject: [PATCH 003/373] removed unwanted code --- controllers/v1/library/categories.js | 195 ----- controllers/v1/reports.js | 61 -- controllers/v1/userProjects.js | 705 ---------------- module/library/categories/helper.js | 232 ------ module/library/categories/validator/v1.js | 5 - module/userProjects/helper.js | 926 ---------------------- module/userProjects/validator/v1.js | 15 - 7 files changed, 2139 deletions(-) diff --git a/controllers/v1/library/categories.js b/controllers/v1/library/categories.js index 6f19b572..b8f6cad3 100644 --- a/controllers/v1/library/categories.js +++ b/controllers/v1/library/categories.js @@ -36,85 +36,6 @@ module.exports = class LibraryCategories extends Abstract { return "projectCategories"; } - /** - * @api {get} /improvement-project/api/v1/library/categories/list - * List of library categories. - * @apiVersion 1.0.0 - * @apiGroup Library Categories - * @apiSampleRequest /improvement-project/api/v1/library/categories/list - * @apiParamExample {json} Response: - { - "message": "Project categories fetched successfully", - "status": 200, - "result": [ - { - "name": "Community", - "type": "community", - "updatedAt": "2020-11-18T16:03:22.563Z", - "projectsCount": 0, - "url": "https://storage.googleapis.com/download/storage/v1/b/sl-dev-storage/o/static%2FprojectCategories%2Fcommunity.png?alt=media" - }, - { - "name": "Education Leader", - "type": "educationLeader", - "updatedAt": "2020-11-18T16:03:22.563Z", - "projectsCount": 0, - "url": "https://storage.googleapis.com/download/storage/v1/b/sl-dev-storage/o/static%2FprojectCategories%2FeducationLeader.png?alt=media" - }, - { - "name": "Infrastructure", - "type": "infrastructure", - "updatedAt": "2020-11-18T16:03:22.563Z", - "projectsCount": 0, - "url": "https://storage.googleapis.com/download/storage/v1/b/sl-dev-storage/o/static%2FprojectCategories%2Finfrastructure.png?alt=media" - }, - { - "name": "Students", - "type": "students", - "updatedAt": "2020-11-18T16:03:22.563Z", - "projectsCount": 0, - "url": "https://storage.googleapis.com/download/storage/v1/b/sl-dev-storage/o/static%2FprojectCategories%2Fstudents.png?alt=media" - }, - { - "name": "Teachers", - "type": "teachers", - "updatedAt": "2020-11-18T16:03:22.563Z", - "projectsCount": 0, - "url": "https://storage.googleapis.com/download/storage/v1/b/sl-dev-storage/o/static%2FprojectCategories%2Fteachers.png?alt=media" - } - ]} - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * List of library categories - * @method - * @name list - * @returns {Array} Library categories. - */ - - async list() { - return new Promise(async (resolve, reject) => { - try { - - let projectCategories = await libraryCategoriesHelper.list(); - - projectCategories.result = projectCategories.data; - - return resolve(projectCategories); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** * @api {get} /improvement-project/api/v1/library/categories/projects/:categoryExternalId?page=:page&limit=:limit&search=:search&sort=:sort * List of library projects. @@ -176,120 +97,4 @@ module.exports = class LibraryCategories extends Abstract { }) } - /** - * @api {get} /improvement-project/api/v1/library/categories/projectDetails/:projectId - * Library projects details. - * @apiVersion 1.0.0 - * @apiGroup Library Categories - * @apiSampleRequest /improvement-project/api/v1/library/categories/projectDetails/5f2ab0a33f623cb3b25c846a - * @apiParamExample {json} Response: - * { - "message": "Successfully fetched projects", - "status": 200, - "result": - { - "_id": "5f2ab0a33f623cb3b25c846a", - "status": "pending", - "createdAt": "2020-06-29T05:38:43.408Z", - "lastDownloadedAt": "2020-06-29T05:38:43.408Z", - "syncedAt": "2020-06-29T05:38:43.408Z", - "isDeleted": false, - "category": [ - { - "_id": "5f102331665bee6a740714e9", - "name": "Students", - "externalId": "students" - } - ], - "createdBy": "e97b5582-471c-4649-8401-3cc4249359bb", - "startedAt": "2020-06-29T05:38:43.408Z", - "completedAt": "2020-06-29T05:38:43.408Z", - "tasks": [ - { - "_id": "5f24404784504944928b10bc", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [ - { - "_id": "5f24404784504944928b10bd", - "createdBy": "e97b5582-471c-4649-8401-3cc4249359bb", - "updatedBy": "e97b5582-471c-4649-8401-3cc4249359bb", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [], - "deleted": false, - "type": "single", - "projectTemplateId": "5f2402f570d11462f8e9a591", - "name": "Sub-Task-4", - "externalId": "sub-task-4", - "description": "Sub Task-4-details", - "updatedAt": "2020-07-31T16:25:01.405Z", - "createdAt": "2020-07-31T16:01:11.286Z", - "__v": 0, - "parentId": "5f24404784504944928b10bc" - } - ], - "deleted": false, - "type": "multiple", - "projectTemplateId": "5f2402f570d11462f8e9a591", - "name": "Task-3", - "externalId": "Task-3", - "description": "Task-3details", - "updatedAt": "2020-07-31T16:25:01.430Z", - "createdAt": "2020-07-31T16:01:11.280Z" - } - ], - "entityInformation": { - "externalId": "1959076", - "name": "Nigam Pratibha Vidyalaya (Girls), Jauna Pur, New Delhi" - }, - "solutionInformation": { - "externalId": "EF-DCPCR-2018-001", - "name": "DCPCR Assessment Framework 2018", - "description": "DCPCR Assessment Framework 2018", - "_id": "5b98fa069f664f7e1ae7498c" - }, - "entityTypeId": "5ce23d633c330302e720e65f", - "programInformation": { - "externalId": "PROGID01", - "name": "DCPCR School Development Index 2018-19", - "description": "DCPCR School Development Index 2018-19" - }, - "title": "Improving Library", - "goal": "Improving Library", - "duration": "1 weeak" - } - } - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * List of library projects - * @method - * @name projects - * @returns {JSON} returns a list of library projects. - */ - - async projectDetails(req) { - return new Promise(async (resolve, reject) => { - try { - - let libraryProjectDetails = - await libraryCategoriesHelper.projectDetails( - req.params._id, - req.userDetails.userToken - ); - - libraryProjectDetails.result = libraryProjectDetails.data; - return resolve(libraryProjectDetails); - - } catch (error) { - return reject(error); - } - }) - } - }; diff --git a/controllers/v1/reports.js b/controllers/v1/reports.js index 1314ae7f..4d9e09fc 100644 --- a/controllers/v1/reports.js +++ b/controllers/v1/reports.js @@ -95,67 +95,6 @@ module.exports = class Reports { }) } - /** - * @api {get} /improvement-project/api/v1/reports/types - * Get report types. - * @apiVersion 1.0.0 - * @apiGroup Reports - * @apiSampleRequest /improvement-project/api/v1/reports/types - * @apiParamExample {json} Response: - * { - "message": "Report types fetched successfully.", - "status": 200, - "result": [ - { - "message": "Report types fetched successfully.", - "status": 200, - "result": [ - { - "label": "Weekly", - "value": 0 - }, - { - "label": "Monthly", - "value": 1 - }, - { - "label": "Quarterly", - "value": 3 - } - - ] - * } - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * Get entity types - * @method - * @name types - * @returns {JSON} enity report details. - */ - async types(req) { - return new Promise(async (resolve, reject) => { - try { - - const reportTypes = await reportsHelper.types(); - - return resolve({ - message: reportTypes.message, - result: reportTypes.data - }); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - /** * @api {get} /improvement-project/api/v1/reports/getProgramsByEntity/:_id * Get programs by entity. diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 31fd1fbe..bda91e66 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -36,581 +36,6 @@ module.exports = class UserProjects extends Abstract { return "userProjects"; } - /** - * @api {get} /improvement-project/api/v1/userProjects/list?updateLastDownloadedAt=:updateLastDownloadedAt - * List of projects. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/list?updateLastDownloadedAt=true - * @apiParamExample {json} Response: - * { - "message": "Project lists fetched successfully", - "status": 200, - "result": [ - { - "_id": "5f2449eb626a540f40817ef5", - "userId": "e97b5582-471c-4649-8401-3cc4249359bb", - "status": "pending", - "createdAt": "2020-06-29T05:38:43.408Z", - "lastDownloadedAt": "2020-06-29T05:38:43.408Z", - "syncedAt": "2020-06-29T05:38:43.408Z", - "isDeleted": false, - "category": [ - "Community" - ], - "createdBy": "e97b5582-471c-4649-8401-3cc4249359bb", - "startedAt": "2020-06-29T05:38:43.408Z", - "completedAt": "2020-06-29T05:38:43.408Z", - "tasks": [ - { - "_id": "5f24404784504944928b10bc", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [ - { - "_id": "5f24404784504944928b10bd", - "createdBy": "e97b5582-471c-4649-8401-3cc4249359bb", - "updatedBy": "e97b5582-471c-4649-8401-3cc4249359bb", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [], - "deleted": false, - "type": "single", - "projectTemplateId": "5f2402f570d11462f8e9a591", - "name": "Sub-Task-4", - "externalId": "sub-task-4", - "description": "Sub Task-4-details", - "updatedAt": "2020-07-31T16:25:01.405Z", - "createdAt": "2020-07-31T16:01:11.286Z", - "__v": 0, - "parentId": "5f24404784504944928b10bc" - } - ], - "deleted": false, - "type": "multiple", - "projectTemplateId": "5f2402f570d11462f8e9a591", - "name": "Task-3", - "externalId": "Task-3", - "description": "Task-3details", - "updatedAt": "2020-07-31T16:25:01.430Z", - "createdAt": "2020-07-31T16:01:11.280Z" - } - ], - "entityInformation": { - "externalId": "1959076", - "name": "Nigam Pratibha Vidyalaya (Girls), Jauna Pur, New Delhi" - }, - "solutionInformation": { - "externalId": "EF-DCPCR-2018-001", - "name": "DCPCR Assessment Framework 2018", - "description": "DCPCR Assessment Framework 2018", - "_id": "5b98fa069f664f7e1ae7498c" - }, - "entityTypeId": "5ce23d633c330302e720e65f", - "programInformation": { - "externalId": "PROGID01", - "name": "DCPCR School Development Index 2018-19", - "description": "DCPCR School Development Index 2018-19" - }, - "title": "Improving Library", - "goal": "Improving Library", - "duration": "1 weeak" - } - ] - } - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * List of project - * @method - * @name list - * @param {Object} req - request data. - * @returns {JSON} returns a list of project. - */ - - async list(req) { - return new Promise(async (resolve, reject) => { - try { - - let projects = await userProjectsHelper.list( - req.userDetails.userInformation.userId, - req.query.updateLastDownloadedAt ? req.query.updateLastDownloadedAt : false - ); - - projects.result = projects.data; - - return resolve(projects); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** - * @api {get} /improvement-project/api/v1/userProjects/metaForm - * Projects metaForm. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/metaForm - * @apiParamExample {json} Response: - * { - * "message": "Successfully fetched projects metaform", - * "status": 200, - * "result": [ - { - "field": "title", - "label": "Title", - "value": "", - "visible": true, - "editable": true, - "input": "text", - "validation": { - "required": true - } - }, - { - "field": "description", - "label": "Description", - "value": "", - "visible": true, - "editable": true, - "input": "textarea", - "validation": { - "required": true - } - }, - { - "field": "categories", - "label": "Categories", - "value": "", - "visible": true, - "editable": true, - "input": "select", - "options": [ - { - "_id": "5fbb2bcc3e7f4958654e351e", - "label": "Teachers", - "value": "teachers" - }, - { - "_id": "5fbb2bcc3e7f4958654e351f", - "label": "Students", - "value": "students" - }, - { - "_id": "5fbb2bcc3e7f4958654e3520", - "label": "Infrastructure", - "value": "infrastructure" - }, - { - "_id": "5fbb2bcc3e7f4958654e3521", - "label": "Community", - "value": "community" - }, - { - "_id": "5fbb2bcc3e7f4958654e3522", - "label": "Education Leader", - "value": "educationLeader" - }, - { - "_id": "", - "label": "Others", - "value": "others" - } - ], - "validation": { - "required": false - } - }]} - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * Projects form - * @method - * @name metaForm - * @param {Object} req - request data. - * @returns {JSON} Projects form. - */ - - async metaForm(req) { - return new Promise(async (resolve, reject) => { - try { - - const formsData = - await userProjectsHelper.metaForm(req.userDetails.userToken); - - formsData.result = formsData.data; - return resolve(formsData); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** - * @api {get} /improvement-project/api/v1/userProjects/tasksMetaForm - * Projects task meta form. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/tasksMetaForm - * @apiParamExample {json} Response: - * { - "message": "Successfully fetched projects tasks metaform", - "status": 200, - "result": [ - { - "field": "name", - "label": "Name", - "value": "", - "visible": true, - "editable": true, - "input": "text", - "validation": { - "required": true - } - }, - { - "field": "description", - "label": "Description", - "value": "", - "visible": true, - "editable": true, - "input": "textarea", - "validation": { - "required": true - } - } - ] - } - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * Projects tasks meta form. - * @method - * @name tasksMetaForm - * @param {Object} req - request data. - * @returns {JSON} Projects tasks meta form. - */ - - async tasksMetaForm() { - return new Promise(async (resolve, reject) => { - try { - - let formsData = await userProjectsHelper.tasksMetaForm(); - - formsData.result = formsData.data; - return resolve(formsData); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** - * @api {post} /improvement-project/api/v1/userProjects/bulkCreate - * Bulk create user projects. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiParam {File} projects Mandatory project file of type CSV. - * @apiSampleRequest /improvement-project/api/v1/userProjects/bulkCreate - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * Bulk create user projects. - * @method - * @name bulkCreate - * @param {Object} req - request data. - * @returns {CSV} Assigned projects to user. - */ - - async bulkCreate(req) { - return new Promise(async (resolve, reject) => { - try { - - if ( !req.files || !req.files.projects ) { - return resolve( - { - status : HTTP_STATUS_CODE["bad_request"].status, - message : CONSTANTS.apiResponses.PROJECTS_CSV_REQUIRED - } - ) - } - - const projectsData = await csv().fromString( - req.files.projects.data.toString() - ); - - const projects = await userProjectsHelper.bulkCreate( - projectsData, - req.userDetails.userToken - ); - - return resolve(projects); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** - * @api {post} /improvement-project/api/v1/userProjects/importFromLibrary/:projectTemplateId - * Import project from library. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/importFromLibrary/5f5b32cef16777642d51aaf0 - * @apiParamExample {json} Request: - * { - * "programId" : "", - * "programName" : "My Program", - * "rating" : 2 - * } - * @apiParamExample {json} Response: - * { - "message": "Successfully fetched projects", - "status": 200, - "result": { - "userId": "01c04166-a65e-4e92-a87b-a9e4194e771d", - "createdFor": [], - "isDeleted": false, - "categories": [ - { - "_id": "5f102331665bee6a740714eb", - "externalId": "community", - "name": "Community" - } - ], - "createdBy": "01c04166-a65e-4e92-a87b-a9e4194e771d", - "tasks": [ - { - "_id": "61d6690d-82cb-4db2-8191-8dd945c5e742", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [ - { - "_id": "b5068cef-eefc-4f43-8a29-ab9c2268f451", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [], - "visibleIf": [ - { - "operator": "===", - "_id": "5f72f9998925ec7c60f79a91", - "value": "started" - } - ], - "deleted": false, - "type": "single", - "projectTemplateId": "5f5b32cef16777642d51aaf0", - "name": "Sub task 1", - "externalId": "Sub-task-1", - "description": "Sub-Task-1-Description", - "updatedAt": "2020-09-29T09:08:41.681Z", - "createdAt": "2020-09-29T09:08:41.675Z", - "__v": 0, - "status": "notStarted" - }, - { - "_id": "988ef20f-267f-4bed-9a38-9d7dc6a320e9", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [], - "visibleIf": [ - { - "operator": "===", - "_id": "5f72f9998925ec7c60f79a91", - "value": "started" - } - ], - "deleted": false, - "type": "single", - "projectTemplateId": "5f5b32cef16777642d51aaf0", - "name": "Sub task 2", - "externalId": "Sub-task-2", - "description": "Sub-Task-2-Description", - "updatedAt": "2020-09-29T09:08:41.693Z", - "createdAt": "2020-09-29T09:08:41.689Z", - "__v": 0, - "status": "notStarted" - } - ], - "visibleIf": [], - "deleted": false, - "type": "multiple", - "projectTemplateId": "5f5b32cef16777642d51aaf0", - "name": "Task 1", - "externalId": "task-1", - "description": "Task-1 Description", - "updatedAt": "2020-09-29T09:08:41.691Z", - "createdAt": "2020-09-29T09:08:41.612Z", - "__v": 0, - "status": "notStarted" - }, - { - "_id": "289d9558-b98f-41cf-81d3-92486f114a49", - "isDeleted": false, - "isDeletable": false, - "taskSequence": [], - "children": [], - "visibleIf": [], - "deleted": false, - "type": "single", - "projectTemplateId": "5f5b32cef16777642d51aaf0", - "name": "Task 12", - "externalId": "Task-12", - "description": "Task-1 Description", - "updatedAt": "2020-09-29T09:08:41.667Z", - "createdAt": "2020-09-29T09:08:41.667Z", - "__v": 0, - "status": "notStarted" - } - ], - "updatedBy": "01c04166-a65e-4e92-a87b-a9e4194e771d", - "rootOrganisations": [], - "_id": "5f731d68920a8c3e092e6e4c", - "deleted": false, - "name": "Test-2", - "description": "improving school library", - "status": "notStarted", - "updatedAt": "2020-09-29T11:41:28.656Z", - "createdAt": "2020-09-11T08:18:22.077Z", - "__v": 0, - "solutionInformation": { - "externalId": "01c04166-a65e-4e92-a87b-a9e4194e771d-1601379673400" - }, - "programInformation": { - "externalId": "My Program-1601379673400", - "name": "My Program" - }, - "taskReport": {}, - "entityInformation": {}, - "rationale": "sample", - "primaryAudience": [ - "teachers", - "head master" - ] - }} - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * Import project from library. - * @method - * @name importFromLibrary - * @param {Object} req - request data. - * @param {String} req.params._id - project Template Id. - * @returns {JSON} import project from library. - */ - - async importFromLibrary(req) { - return new Promise(async (resolve, reject) => { - try { - - const createdProject = await userProjectsHelper.importFromLibrary( - req.params._id, - req.body, - req.userDetails.userToken, - req.userDetails.userInformation.userId - ); - - return resolve({ - message: createdProject.message, - result: createdProject.data - }); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** - * @api {get} /improvement-project/api/v1/userProjects/create - * Create project. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/create - * @apiParamExample {json} Response: - * { - "message": "Created user project successfully", - "status": 200, - "result": { - "_id": "5f97d2f6bf3a3b1c0116c80a", - "lastDownloadedAt": "2020-10-27T07:57:41.003Z" - }} - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * Create project. - * @method - * @name create - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @returns {JSON} Create project. - */ - - async create(req) { - return new Promise(async (resolve, reject) => { - try { - - let createdProject = await userProjectsHelper.create( - req.userDetails.userInformation.userId, - req.userDetails.userToken - ); - - createdProject.result = createdProject.data; - - return resolve(createdProject); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - /** * @api {post} /improvement-project/api/v1/userProjects/sync/:projectId?lastDownloadedAt=:epochTime * Sync project. @@ -1000,136 +425,6 @@ module.exports = class UserProjects extends Abstract { } }) } - - - /** - * @api {post} /improvement-project/api/v1/userProjects/bulkCreateByUserRoleAndEntity - * Bulk create user projects by entity and role. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/bulkCreateByUserRoleAndEntity - * @apiParamExample {json} Request: - * { - * "templateId": "5f2449eb626a540f40817ef5", - * "entityId": "5f2449eb626a540f40817ef5", - * "role": "CRP", - * "programExternalId": "TAF-pgm", - * "solutionExternalId": "TAF-solution" - } - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * Bulk create user projects by entity and role. - * @method - * @name bulkCreateByUserRoleAndEntity - * @param {Object} req - request data. - * @param {String} req.body.entityId - entityId - * @param {String} req.body.role - role - * @returns {CSV} Assigned projects to user. - */ - - async bulkCreateByUserRoleAndEntity(req) { - return new Promise(async (resolve, reject) => { - try { - - let projects = await userProjectsHelper.bulkCreateByUserRoleAndEntity( - req.body, - req.userDetails.userToken - ); - - return resolve(projects); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** - * @api {post} /improvement-project/api/v1/userProjects/getProject?page=:page&limit=:limit&search=:search&filter=:assignedToMe - * List of User projects and auto targeted. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/getProject - * @apiParamExample {json} Request: - * { - * "role" : "HM", - "state" : "236f5cff-c9af-4366-b0b6-253a1789766a", - "district" : "1dcbc362-ec4c-4559-9081-e0c2864c2931", - "school" : "c5726207-4f9f-4f45-91f1-3e9e8e84d824" - } - * @apiParamExample {json} Response: - { - "message": " Targeted projects fetched successfully", - "status": 200, - "result": { - "description": "Manage and track your school Improvement easily by creating tasks and planning timelines.", - "data": [ - { - "_id": "5fd6f3b6062df5269e6532f0", - "description": "h bucks ", - "programId": "5fd6f3b7ab86c4262564b83f", - "solutionId": "5fd6f3b7ab86c4262564b840", - "name": "gjk" - }, - { - "_id": "", - "externalId": "TAMIL-NADU-AUTO-TARGETING-IMPROVEMENT-PROJECT", - "programId": "5ffbf8909259097d48017bbf", - "programName": "Tamil nadu AUTO TARGETING program", - "description": "tamil nadu improvement project testing", - "name": "tamil nadu improvement project testing", - "solutionId": "5ffbf9629259097d48017bc0" - } - ], - "count": 2 - } - } - * @apiUse successBody - * @apiUse errorBody - */ - - /** - * List of user projects and targetted ones. - * @method - * @name getProject - * @param {Object} req - request data. - * @returns {JSON} List of user project with targetted ones. - */ - - async getProject(req) { - return new Promise(async (resolve, reject) => { - try { - - let projects = await userProjectsHelper.getProject( - req.body, - req.userDetails.userInformation.userId, - req.userDetails.userToken, - req.pageSize, - req.pageNo, - req.searchText, - req.query.filter - ); - - projects.result = projects.data; - - return resolve(projects); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } /** * @api {post} /improvement-project/api/v1/userProjects/add diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index 9e2425f1..12386e04 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -70,108 +70,6 @@ module.exports = class LibraryCategoriesHelper { }); } - /** - * List of project categories. - * @method - * @name list - * @returns {Object} Project categories. - */ - - static list() { - return new Promise(async (resolve, reject) => { - try { - - let projectCategoriesData = - await this.categoryDocuments( - { - status : CONSTANTS.common.ACTIVE_STATUS - }, - [ - "externalId", - "name", - "icon", - "updatedAt", - "noOfProjects" - ] - ); - - if( !projectCategoriesData.length > 0 ) { - throw { - status : HTTP_STATUS_CODE['ok'].status, - message : CONSTANTS.apiResponses.LIBRARY_CATEGORIES_NOT_FOUND - }; - } - - - let categories = {}; - let icons = []; - - projectCategoriesData.map(category => { - - categories[category.icon] = { - name : category.name, - type : category.externalId, - updatedAt : category.updatedAt, - projectsCount : category.noOfProjects ? category.noOfProjects : 0 - }; - - if( category.icon !== "" ) { - icons.push(category.icon); - } - - }); - - let projectCategories = ""; - - if( icons.length > 0 ) { - - projectCategories = - await kendraService.getDownloadableUrl( - { - filePaths : icons - } - ); - - if( !projectCategories.success ) { - throw { - status : HTTP_STATUS_CODE['bad_request'].status, - message : CONSTANTS.apiResponses.KENDRA_URL_NOT_FETCHED - } - } - - projectCategories = - projectCategories.data.map( downloadableImage => { - return _.merge( - categories[downloadableImage.filePath], - { url : downloadableImage.url } - ) - }); - - } else { - projectCategories = Object.values(categories); - } - - projectCategories = projectCategories.sort((a,b)=> a.name.toString() > b.name.toString() ? 1 : -1); - - return resolve({ - success: true, - message : CONSTANTS.apiResponses.PROJECT_CATEGORIES_FETCHED, - data : projectCategories - }); - - } catch (error) { - return resolve({ - status : - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] - }); - } - }) - } - /** * List of library projects. * @method @@ -288,136 +186,6 @@ module.exports = class LibraryCategoriesHelper { }) } - /** - * Details of library projects. - * @method - * @name projectDetails - * @param projectId - project internal id. - * @returns {Object} Details of library projects. - */ - - static projectDetails(projectId,userToken = "") { - return new Promise(async (resolve, reject) => { - try { - - let projectsData = - await database.models.projectTemplates.find( - { - status : CONSTANTS.common.PUBLISHED, - "_id" : projectId, - "isDeleted" : false - },{ - "__v" : 0 - } - ).lean(); - - if( !projectsData.length > 0 ) { - throw { - status : HTTP_STATUS_CODE['bad_request'].status, - message : CONSTANTS.apiResponses.PROJECT_NOT_FOUND, - }; - } - - projectsData[0].showProgramAndEntity = false; - - if( projectsData[0].tasks && projectsData[0].tasks.length > 0 ) { - - let tasks = - await database.models.projectTemplateTasks.find({ - _id : { - $in : projectsData[0].tasks - }, - isDeleted : false - }).lean(); - - if( tasks && tasks.length > 0 ) { - - let taskData = {}; - - for ( - let taskPointer = 0; - taskPointer < tasks.length; - taskPointer ++ - ) { - let currentTask = tasks[taskPointer]; - - if( - currentTask.type === CONSTANTS.common.ASSESSMENT || - currentTask.type === CONSTANTS.common.OBSERVATION - ) { - projectsData[0].showProgramAndEntity = true; - } - - if( currentTask.parentId && currentTask.parentId !== "" ) { - - if( !taskData[currentTask.parentId.toString()] ) { - taskData[currentTask.parentId.toString()].children = []; - } - - taskData[currentTask.parentId.toString()].children.push( - _.omit(currentTask,["parentId"]) - ); - - } else { - currentTask.children = []; - taskData[currentTask._id.toString()] = currentTask; - } - - - } - - projectsData[0].tasks = Object.values(taskData); - - } - } - - if( userToken !== "" ) { - - let userProfileData = await kendraService.getProfile(userToken); - - if( !userProfileData.success ) { - throw { - status : HTTP_STATUS_CODE['bad_request'].status, - message : CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND - } - } - - projectsData[0].userRating = 0; - - if( - userProfileData.data && - userProfileData.data.ratings && - userProfileData.data.ratings.length > 0 - ) { - - let projectIndex = - userProfileData.data.ratings.findIndex( - project => project._id.toString() === projectId.toString() - ); - - if( projectIndex > 0 ) { - projectsData[0].userRating = userProfileData.data.ratings[projectIndex].rating; - } - } - } - - return resolve({ - success: true, - message : CONSTANTS.apiResponses.PROJECTS_FETCHED, - data : projectsData[0] - }); - - } catch (error) { - return resolve({ - status : error.status ? error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data : {} - }); - } - }) - } - /** * Update categories * @method diff --git a/module/library/categories/validator/v1.js b/module/library/categories/validator/v1.js index 8346b8a0..d2d4968e 100644 --- a/module/library/categories/validator/v1.js +++ b/module/library/categories/validator/v1.js @@ -8,11 +8,6 @@ module.exports = (req) => { let projectsValidator = { - projectDetails: function () { - req.checkParams('_id') - .exists() - .withMessage("required project id"); - } } if (projectsValidator[req.params.method]) { diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index d565fb3d..8c09a954 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -69,502 +69,6 @@ module.exports = class UserProjectsHelper { }); } - /** - * List of projects. - * @method - * @name list - * @param {String} userId - logged in user id. - * @param {Boolean} updateLastDownloadedAt - update last downloaded at. - * @returns {Object} Projects. - */ - - static list(userId, updateLastDownloadedAt) { - return new Promise(async (resolve, reject) => { - try { - - let projects = - await this.projectDocument( - { - userId: userId, - isDeleted: false - }, "all", [ - "createdBy", - "updatedBy", - "rootOrganisations", - "taskReport", - "createdFor", - "projectTemplateId", - "projectTemplateExternalId", - "__v" - ]); - - if (!projects.length > 0) { - - throw { - status: HTTP_STATUS_CODE['ok'].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND - }; - } - - let projectIds = []; - - let updatedDate = ""; - - if (updateLastDownloadedAt) { - updatedDate = new Date(); - } - - for (let project = 0; project < projects.length; project++) { - let projectInformation = await _projectInformation(projects[project]); - - if (!projectInformation.success) { - return resolve(projectInformation); - } - - if (updatedDate !== "") { - projectInformation.data.lastDownloadedAt = updatedDate; - } - - projectIds.push(projectInformation.data._id); - } - - if (updatedDate !== "") { - await database.models.projects.updateMany({ - _id: { $in: projectIds } - }, { - $set: { - lastDownloadedAt: updatedDate - } - }); - } - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: projects - }); - - } catch (error) { - return resolve({ - status: error.status ? error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] - }); - } - }) - } - - /** - * List of projects meta form. - * @method - * @name metaForm - * @returns {Object} List of projects meta form. - */ - - static metaForm() { - return new Promise(async (resolve, reject) => { - try { - - let forms = await kendraService.formDetails("projects"); - - if (!forms.success) { - - throw { - status: HTTP_STATUS_CODE['ok'].status, - message: CONSTANTS.apiResponses.PROJECTS_FORM_NOT_FOUND - }; - - } - - let categoriesData = - await libraryCategoriesHelper.categoryDocuments({}, ["name", "externalId"]); - - if (!categoriesData.length > 0) { - - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.LIBRARY_CATEGORIES_NOT_FOUND - }; - - } - - categoriesData = categoriesData.map(category => { - return { - _id: category._id, - label: category.name, - value: category.externalId - }; - }); - - categoriesData.push({ - _id: "", - label: CONSTANTS.common.OTHERS, - value: CONSTANTS.common.OTHERS.toLowerCase() - }); - - let formsData = forms.data; - - formsData[formsData.length - 1].options = categoriesData; - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_METAFORM_FETCHED, - data: formsData - }); - - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] - }); - } - }) - } - - /** - * List of projects tasks meta form. - * @method - * @name tasksMetaForm - * @returns {Object} List of projects tasks meta form. - */ - - static tasksMetaForm() { - return new Promise(async (resolve, reject) => { - try { - - let forms = await kendraService.formDetails("projectTasks"); - - if (!forms.success) { - - throw { - status: HTTP_STATUS_CODE['ok'].status, - message: CONSTANTS.apiResponses.PROJECT_TASKS_FORM_NOT_FOUND - } - } - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_TASKS_METAFORM_FETCHED, - data: forms.data - }); - - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] - }); - } - }) - } - - /** - * Bulk create user projects. - * @method - * @name bulkCreate - Bulk create user projects. - * @param {Array} csvData - csv data. - * @param {String} userToken - logged in user token. - * @returns {Object} Bulk create user projects. - */ - - static bulkCreate(csvData, userToken) { - return new Promise(async (resolve, reject) => { - try { - - const fileName = `bulk-create-user-`; - let fileStream = new CSV_FILE_STREAM(fileName); - let input = fileStream.initStream(); - - (async function () { - await fileStream.getProcessorPromise(); - return resolve({ - isResponseAStream: true, - fileNameWithPath: fileStream.fileNameWithPath() - }); - })(); - - let templateIds = []; - let entityIds = []; - - csvData.forEach(data => { - templateIds.push(data.templateId); - - if (data.entityId && data.entityId !== "") { - entityIds.push(data.entityId); - } - }); - - let entityDocument = {}; - - if (entityIds.length > 0) { - - const entitiesData = await _entitiesInformation(entityIds); - - if (!entitiesData.success) { - return resolve(entitiesData); - } - - entityDocument = - entitiesData.data.reduce((ac, entity) => ({ ...ac, [entity._id.toString()]: entity }), {}); - } - - let templateData = {}; - let solutionIds = []; - let programIds = []; - - if (templateIds.length > 0) { - - const projectTemplates = - await projectTemplatesHelper.templateDocument({ - status: CONSTANTS.common.PUBLISHED, - externalId: { - $in: templateIds - }, - isReusable: false - }, ["_id", "solutionExternalId", "programExternalId", "externalId", "programId"]); - - if (!projectTemplates.length > 0) { - throw { - message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - projectTemplates.forEach(template => { - - templateData[template.externalId] = template; - - if (template.solutionExternalId) { - solutionIds.push(template.solutionExternalId); - } - - if (template.programId) { - programIds.push(template.programId); - } - - }) - - } - - let solutions = {}; - - if (solutionIds.length > 0) { - - let solutionData = - await assessmentService.listSolutions(solutionIds); - - if (!solutionData.success) { - throw { - message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - if ( - solutionData.data && solutionData.data.length > 0 - ) { - solutionData.data.forEach(solution => { - solutions[solution.externalId] = { - "name": solution.name, - "externalId": solution.externalId, - "description": solution.description, - "_id": solution._id - }; - }) - } - - } - - let programs = {}; - - if (programIds.length > 0) { - - let programData = - await assessmentService.listProgramsBasedOnIds(programIds); - - if (!programData.success) { - throw { - message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - if (programData.data && programData.data.length > 0) { - - programData.data.forEach(program => { - programs[program.externalId] = { - _id: program._id, - name: program.name, - description: program.description ? program.description : "", - externalId: program.externalId - }; - }) - } - } - - for ( - let pointerToCsvData = 0; - pointerToCsvData < csvData.length; - pointerToCsvData++ - ) { - - let currentCsvData = csvData[pointerToCsvData]; - - if (!templateData[currentCsvData.templateId]) { - currentCsvData["STATUS"] = - CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; - input.push(currentCsvData); - continue; - } - - let currentTemplateData = templateData[currentCsvData.templateId]; - - let projectCreation = - await this.userAssignedProjectCreation( - currentTemplateData._id, - currentCsvData["keycloak-userId"], - userToken - ); - - if (!projectCreation.success) { - return resolve(projectCreation); - } - - let solutionInformation = {}; - - if (currentTemplateData.solutionExternalId) { - - if (!solutions[currentTemplateData.solutionExternalId]) { - - currentCsvData["STATUS"] = - CONSTANTS.apiResponses.SOLUTION_NOT_FOUND; - input.push(currentCsvData); - continue; - } - - solutionInformation = solutions[currentTemplateData.solutionExternalId]; - projectCreation.data.solutionInformation = solutionInformation; - } - - if (currentTemplateData.programExternalId) { - - if (!programs[currentTemplateData.programExternalId]) { - currentCsvData["STATUS"] = - CONSTANTS.apiResponses.PROGRAM_NOT_FOUND; - input.push(currentCsvData); - continue; - } - - projectCreation.data.programInformation = - programs[currentTemplateData.programExternalId]; - - projectCreation.data.isAPrivateProgram = - programs[currentTemplateData.programExternalId].isAPrivateProgram; - } - - if ( - projectCreation.data.assesmentOrObservationTask && - !currentCsvData.entityId - ) { - currentCsvData["STATUS"] = - CONSTANTS.apiResponses.ENTITY_REQUIRED_FOR_ASSESSMENT_OBSERVATION; - input.push(currentCsvData); - continue; - } - - if (currentCsvData.entityId) { - - if (!entityDocument[currentCsvData.entityId]) { - currentCsvData["STATUS"] = - CONSTANTS.apiResponses.ENTITIES_NOT_FOUND; - input.push(currentCsvData); - continue; - } - - if ( - currentTemplateData.entityType && currentTemplateData.entityType !== "" && - currentTemplateData.entityType !== entityDocument[currentCsvData.entityId].entityType - ) { - currentCsvData["STATUS"] = - CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED; - input.push(currentCsvData); - continue; - } - - let entities = []; - - if ( - solutionInformation.entities && - solutionInformation.entities.length > 0 - ) { - - let entityIndex = - solutionInformation.entities.findIndex(entity => entity._id === csvData[pointerToCsvData].entityId); - - if (entityIndex < 0) { - - entities = - solutionInformation.entities.push(ObjectId(currentCsvData.entityId)) - } - } else { - entities = [ObjectId(currentCsvData.entityId)]; - } - - if (entities.length > 0) { - - let solutionUpdated = - await assessmentService.updateSolution( - userToken, - { - entities: entities - }, - solutionInformation.externalId - ); - - if (!solutionUpdated.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.SOLUTION_NOT_UPDATED - } - } - } - - projectCreation.data.entityId = ObjectId(currentCsvData.entityId); - - projectCreation.data.entityInformation = - entityDocument[currentCsvData.entityId]; - } - - projectCreation.data.status = CONSTANTS.common.NOT_STARTED_STATUS; - projectCreation.data.lastDownloadedAt = new Date(); - const project = - await database.models.projects.create(projectCreation.data); - - if (project._id) { - currentCsvData["STATUS"] = project._id; - } else { - currentCsvData["STATUS"] = CONSTANTS.apiResponses.PROJECT_NOT_CREATED; - } - - input.push(currentCsvData); - } - - input.push(null); - - } catch (error) { - return reject(error); - } - }) - } - /** * Projects boolean data. * @method @@ -619,229 +123,6 @@ module.exports = class UserProjectsHelper { return mongooseIds; } - /** - * Sync project. - * @method - * @name importFromLibrary - * @param {String} projectTemplateId - project template id. - * @param {Object} requestedData - body data. - * @param {String} userId - Logged in user id. - * @param {String} userToken - User token. - * @returns {Object} Project created information. - */ - - static importFromLibrary(projectTemplateId, requestedData, userToken, userId) { - return new Promise(async (resolve, reject) => { - try { - - let libraryProjects = - await libraryCategoriesHelper.projectDetails( - projectTemplateId - ); - - if ( - libraryProjects.data && - !Object.keys(libraryProjects.data).length > 0 - ) { - throw { - message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - }; - } - - let taskReport = {}; - - if ( - libraryProjects.data.tasks && - libraryProjects.data.tasks.length > 0 - ) { - - libraryProjects.data.tasks = await _projectTask( - libraryProjects.data.tasks, - true - ); - - taskReport.total = libraryProjects.data.tasks.length; - - libraryProjects.data.tasks.forEach(task => { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - }); - - libraryProjects.data["taskReport"] = taskReport; - } - - if (requestedData.entityId && requestedData.entityId !== "") { - - let entityInformation = - await _entitiesInformation([requestedData.entityId]); - - if (!entityInformation.success) { - return resolve(entityInformation); - } - - libraryProjects.data["entityInformation"] = entityInformation.data[0]; - libraryProjects.data.entityId = entityInformation.data[0]._id; - } - - if ( - (requestedData.programId && requestedData.programId !== "") || - (requestedData.programName && requestedData.programName !== "") - ) { - - let programAndSolutionInformation = - await this.createProgramAndSolution( - requestedData.programId, - requestedData.programName, - requestedData.entityId ? [requestedData.entityId] : "", - userToken - ); - - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } - - if ( - libraryProjects.data["entityInformation"] && - libraryProjects.data["entityInformation"].entityType !== - programAndSolutionInformation.data.solutionInformation.entityType - ) { - throw { - message: CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - libraryProjects.data = _.merge( - libraryProjects.data, - programAndSolutionInformation.data - ) - } - - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - libraryProjects.data.createdFor = userOrganisations.data.createdFor; - libraryProjects.data.rootOrganisations = userOrganisations.data.rootOrganisations; - - libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; - libraryProjects.data.lastDownloadedAt = new Date(); - libraryProjects.data.status = CONSTANTS.common.NOT_STARTED_STATUS; - - if (requestedData.startDate) { - libraryProjects.data.startDate = requestedData.startDate; - } - - if (requestedData.endDate) { - libraryProjects.data.endDate = requestedData.endDate; - } - - libraryProjects.data.projectTemplateId = libraryProjects.data._id; - libraryProjects.data.projectTemplateExternalId = libraryProjects.data.externalId; - - let projectCreation = await database.models.projects.create( - _.omit(libraryProjects.data, ["_id"]) - ); - - if (requestedData.rating && requestedData.rating > 0) { - await projectTemplatesHelper.ratings( - projectTemplateId, - requestedData.rating, - userToken - ); - } - - projectCreation = await _projectInformation(projectCreation._doc); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: projectCreation.data - }); - - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {} - }); - } - }) - } - - /** - * Create user projects. - * @method - * @name create - * @param userId - Logged in user id. - * @param userToken - Logged in user token. - * @returns {Object} Return _id and lastDownloadedAt - */ - - static create(userId, userToken) { - return new Promise(async (resolve, reject) => { - try { - - let creationData = { - lastDownloadedAt: new Date(), - createdFor: [], - rootOrganisations: [] - } - - creationData["userId"] = creationData["createdBy"] = creationData["updatedBy"] = userId; - - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - if (userOrganisations.data) { - creationData.createdFor = userOrganisations.data.createdFor; - creationData.rootOrganisations = userOrganisations.data.rootOrganisations; - } - - let userProject = await database.models.projects.create( - creationData - ); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.CREATED_USER_PROJECT, - data: _.pick(userProject, ["_id", "lastDownloadedAt"]) - }); - - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); - } - }) - } - /** * Sync project. * @method @@ -1665,57 +946,6 @@ module.exports = class UserProjectsHelper { }) } - /** - * Bulk create user projects By entityId and role. - * @method - * @name bulkCreateByUserRoleAndEntity - Bulk create user projects by entity and role. - * @param {Object} userProjectData - user project data - * @param {String} userToken - logged in user token. - * @returns {Object} Bulk create user projects. - */ - - static bulkCreateByUserRoleAndEntity(userProjectData, userToken) { - return new Promise(async (resolve, reject) => { - try { - - - let userAndEntityList = await kendraService.getUsersByEntityAndRole - ( - userProjectData.entityId, - userProjectData.role - ) - - if (!userAndEntityList.success || !userAndEntityList.data) { - throw { - message: CONSTANTS.apiResponses.USERS_AND_ENTITIES_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - let userProjectBulkCreationData = []; - - await Promise.all(userAndEntityList.data.map(async user => { - userProjectBulkCreationData.push({ - "templateId": userProjectData.templateId, - "keycloak-userId": user.userId, - "entityId": user.entityId - }) - })); - - let userProjects = await this.bulkCreate - ( - userProjectBulkCreationData, - userToken - ) - - return resolve(userProjects); - - } catch (error) { - return reject(error); - } - }) - } - /** * User assigned project creation data. * @method @@ -1837,162 +1067,6 @@ module.exports = class UserProjectsHelper { }); } - /** -* Get list of user projects with the targetted ones. -* @method -* @name getProject -* @param {String} userId - Logged in user id. -* @param {String} userToken - Logged in user token. -* @returns {Object} -*/ - - static getProject(bodyData, userId, userToken, pageSize, pageNo, search, filter) { - return new Promise(async (resolve, reject) => { - try { - - let query = { - userId: userId, - isDeleted: false - } - - let searchQuery = []; - - if (search !== "") { - searchQuery = [ - { "title": new RegExp(search, 'i') }, - { "description": new RegExp(search, 'i') } - ]; - } - - bodyData["filter"] = {}; - - if (filter && filter !== "") { - if (filter === CONSTANTS.common.CREATED_BY_ME) { - query["isAPrivateProgram"] = bodyData["filter"]["isAPrivateProgram"] = { - "$ne": false - }; - } else if (filter == CONSTANTS.common.ASSIGN_TO_ME) { - query["isAPrivateProgram"] = bodyData["filter"]["isAPrivateProgram"] = false; - } - } - - let projects = await this.projects( - query, - CONSTANTS.common.DEFAULT_PAGE_SIZE, - CONSTANTS.common.DEFAULT_PAGE_NO, - searchQuery, - [ - "title", - "description", - "solutionId", - "programId", - "programInformation.name", - "projectTemplateId", - "solutionExternalId", - "lastDownloadedAt", - "hasAcceptedTAndC" - ] - ); - - let solutionIds = []; - - let totalCount = 0; - let mergedData = []; - - if (projects.success && projects.data) { - - totalCount = projects.data.count; - mergedData = projects.data.data; - - if (mergedData.length > 0) { - mergedData.forEach(projectData => { - projectData.name = projectData.title; - - if (projectData.programInformation) { - projectData.programName = projectData.programInformation.name; - delete projectData.programInformation; - } - - if (projectData.solutionExternalId) { - projectData.externalId = projectData.solutionExternalId; - delete projectData.solutionExternalId; - } - - projectData.type = CONSTANTS.common.IMPROVEMENT_PROJECT; - - if (projectData.solutionId) { - solutionIds.push(projectData.solutionId); - } - - delete projectData.title; - }); - } - } - - if (solutionIds.length > 0) { - bodyData["filter"]["skipSolutions"] = solutionIds; - } - - bodyData.filter["projectTemplateId"] = { - $exists: true - }; - - let targetedSolutions = - await kendraService.solutionBasedOnRoleAndLocation( - userToken, - bodyData, - CONSTANTS.common.IMPROVEMENT_PROJECT, - search - ); - - if (targetedSolutions.success) { - - if (targetedSolutions.data.data && targetedSolutions.data.data.length > 0) { - totalCount += targetedSolutions.data.count; - - if (mergedData.length !== pageSize) { - - targetedSolutions.data.data.forEach(targetedSolution => { - targetedSolution.solutionId = targetedSolution._id; - targetedSolution._id = ""; - mergedData.push(targetedSolution); - }) - } - } - } - - if (mergedData.length > 0) { - let startIndex = pageSize * (pageNo - 1); - let endIndex = startIndex + pageSize; - mergedData = mergedData.slice(startIndex, endIndex); - } - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.TARGETED_PROJECT_FETCHED, - data: { - description: CONSTANTS.common.PROJECT_DESCRIPTION, - data: mergedData, - count: totalCount - } - }); - } catch (error) { - return resolve({ - success : false, - message : error.message, - status : - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - data : { - description : CONSTANTS.common.PROJECT_DESCRIPTION, - data : [], - count : 0 - } - }); - } - }) - } - /** * Creation of user targeted projects. * @method diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index c0d63cd7..cf91e78b 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -9,13 +9,6 @@ module.exports = (req) => { let projectsValidator = { - createSelf : function () { - req.checkBody('title').exists().withMessage("required project title"); - req.checkBody('categories').exists().withMessage("required categories for project"); - }, - importFromLibrary : function () { - req.checkParams('_id').exists().withMessage("required project template id"); - }, sync : function () { req.checkParams('_id').exists().withMessage("required project id"); req.checkQuery('lastDownloadedAt').exists().withMessage("required last downloaded at"); @@ -23,18 +16,10 @@ module.exports = (req) => { details : function () { req.checkParams('_id').exists().withMessage("required project id"); }, - tasksStatus : function () { - req.checkParams('_id').exists().withMessage("required project id"); - }, solutionDetails : function () { req.checkParams('_id').exists().withMessage("required project id"); req.checkQuery('taskId').exists().withMessage("required task id"); }, - bulkCreateByUserRoleAndEntity : function () { - req.checkBody('templateId').exists().withMessage("required template id"); - req.checkBody('entityId').exists().withMessage("required entity id"); - req.checkBody('role').exists().withMessage("required role"); - }, add : function () { req.checkBody('title').exists().withMessage("required project title"); }, From 4c7e4b301adaec1800935e96bac179604c17a76e Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Tue, 31 Aug 2021 12:15:06 +0530 Subject: [PATCH 004/373] Added console.log in kendra service --- generics/services/kendra.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/generics/services/kendra.js b/generics/services/kendra.js index 9919031e..80024e7f 100644 --- a/generics/services/kendra.js +++ b/generics/services/kendra.js @@ -696,10 +696,12 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution }; if (err) { + console.log("solution details error is",err); result.success = false; } else { let response = data.body; + console.log("solution details response is",response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; @@ -754,10 +756,12 @@ const getUserOrganisationsAndRootOrganisations = function ( token,userId = "" ) }; if (err) { + console.log("-- get user organisation and root organisation issue ---",err); result.success = false; } else { let response = JSON.parse(data.body); + console.log("-- get user organisation and root organisation success ---",response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { From 0df47544578627e97a51e80c44596f011a7a98da Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Tue, 31 Aug 2021 12:17:35 +0530 Subject: [PATCH 005/373] Added log in kendra service --- generics/services/kendra.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/generics/services/kendra.js b/generics/services/kendra.js index 80024e7f..aad482ea 100644 --- a/generics/services/kendra.js +++ b/generics/services/kendra.js @@ -677,6 +677,7 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution const url = KENDRA_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId; + console.log("solution details url",url) const options = { headers : { @@ -740,6 +741,8 @@ const getUserOrganisationsAndRootOrganisations = function ( token,userId = "" ) url = url + "/" + userId; } + console.log("user organisations url",url) + const options = { headers : { "content-type": "application/json", @@ -756,12 +759,12 @@ const getUserOrganisationsAndRootOrganisations = function ( token,userId = "" ) }; if (err) { - console.log("-- get user organisation and root organisation issue ---",err); + console.log("--user organisation and root organisation issue ---",err); result.success = false; } else { let response = JSON.parse(data.body); - console.log("-- get user organisation and root organisation success ---",response); + console.log("-- user organisation and root organisation success ---",response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { From 7deb25561cc250df7553a56a77a2deb3a3fdd8ba Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Tue, 31 Aug 2021 16:35:16 +0530 Subject: [PATCH 006/373] Removed console.log --- generics/services/kendra.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/generics/services/kendra.js b/generics/services/kendra.js index aad482ea..9919031e 100644 --- a/generics/services/kendra.js +++ b/generics/services/kendra.js @@ -677,7 +677,6 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution const url = KENDRA_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId; - console.log("solution details url",url) const options = { headers : { @@ -697,12 +696,10 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution }; if (err) { - console.log("solution details error is",err); result.success = false; } else { let response = data.body; - console.log("solution details response is",response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; @@ -741,8 +738,6 @@ const getUserOrganisationsAndRootOrganisations = function ( token,userId = "" ) url = url + "/" + userId; } - console.log("user organisations url",url) - const options = { headers : { "content-type": "application/json", @@ -759,12 +754,10 @@ const getUserOrganisationsAndRootOrganisations = function ( token,userId = "" ) }; if (err) { - console.log("--user organisation and root organisation issue ---",err); result.success = false; } else { let response = JSON.parse(data.body); - console.log("-- user organisation and root organisation success ---",response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { From 7d893d79468014ec915474c92a052ab61f5aad52 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 1 Sep 2021 10:38:09 +0530 Subject: [PATCH 007/373] structure change --- config/globals.js | 1 + module/library/categories/helper.js | 64 +------- module/project/templateTasks/helper.js | 65 ++------ module/project/templates/helper.js | 204 +++++++----------------- module/reports/helper.js | 5 +- module/userProjects/helper.js | 212 +++---------------------- services/projectCategories.js | 98 ++++++++++++ services/projectTemplateTask.js | 156 ++++++++++++++++++ services/projectTemplates.js | 178 +++++++++++++++++++++ services/projects.js | 131 +++++++++++++++ 10 files changed, 661 insertions(+), 453 deletions(-) create mode 100644 services/projectCategories.js create mode 100644 services/projectTemplateTask.js create mode 100644 services/projectTemplates.js create mode 100644 services/projects.js diff --git a/config/globals.js b/config/globals.js index 02a1341d..4c6a458a 100644 --- a/config/globals.js +++ b/config/globals.js @@ -15,6 +15,7 @@ module.exports = function () { global.async = require("async"); global.PROJECT_ROOT_DIRECTORY = path.join(__dirname, '..'); global.MODULES_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/module"; + global.DB_SERVICE_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/services"; global.GENERICS_FILES_PATH = PROJECT_ROOT_DIRECTORY + "/generics"; global.GENERIC_HELPERS_PATH = GENERICS_FILES_PATH + "/helpers"; global._ = require("lodash"); diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index 12386e04..5f0247c2 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -8,6 +8,8 @@ // Dependencies const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); const sessionHelpers = require(GENERIC_HELPERS_PATH+"/sessions"); +const projectCategoriesService = require(DB_SERVICE_BASE_PATH + "/projectCategories"); +const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); const moment = require("moment-timezone"); /** @@ -17,59 +19,6 @@ const moment = require("moment-timezone"); module.exports = class LibraryCategoriesHelper { - /** - * Library project categories documents. - * @method - * @name categoryDocuments - * @param {Object} [findQuery = "all"] - filtered data. - * @param {Array} [fields = "all"] - projected data. - * @param {Array} [skipFields = "none"] - fields to skip. - * @returns {Array} - Library project categories data. - */ - - static categoryDocuments( - findQuery = "all", - fields = "all", - skipFields = "none" - ) { - return new Promise(async (resolve, reject) => { - - try { - - let queryObject = {}; - - if (findQuery != "all") { - queryObject = findQuery; - } - - let projection = {}; - - if (fields != "all") { - fields.forEach(element => { - projection[element] = 1; - }); - } - - if (skipFields != "none") { - skipFields.forEach(element => { - projection[element] = 0; - }); - } - - let projectCategoriesData = - await database.models.projectCategories.find( - queryObject, - projection - ).lean(); - - return resolve(projectCategoriesData); - - } catch (error) { - return reject(error); - } - }); - } - /** * List of library projects. * @method @@ -150,8 +99,7 @@ module.exports = class LibraryCategoriesHelper { } }); - let result = - await database.models.projectTemplates.aggregate(aggregateData); + let result = await projectTemplateService.getAggregate(aggregateData); if( result[0].data.length > 0 ) { @@ -199,11 +147,7 @@ module.exports = class LibraryCategoriesHelper { return new Promise(async (resolve, reject) => { try { - let categoriesUpdated = - await database.models.projectCategories.updateMany( - filterQuery, - updateData - ); + let categoriesUpdated = await projectCategoriesService.updateMany(filterQuery,updateData); if( !categoriesUpdated.ok ) { throw { diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index bc53565c..d0958c52 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -14,56 +14,11 @@ const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/helper"); const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); +const projectTemplateTaskService = require(DB_SERVICE_BASE_PATH + "/projectTemplateTask"); +const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); module.exports = class ProjectTemplateTasksHelper { - /** - * Lists of tasks. - * @method - * @name taskDocuments - * @param {Array} [filterData = "all"] - tasks filter query. - * @param {Array} [fieldsArray = "all"] - projected fields. - * @param {Array} [skipFields = "none"] - field not to include - * @returns {Array} Lists of tasks. - */ - - static taskDocuments( - filterData = "all", - fieldsArray = "all", - skipFields = "none" - ) { - return new Promise(async (resolve, reject) => { - try { - - let queryObject = (filterData != "all") ? filterData : {}; - let projection = {} - - if (fieldsArray != "all") { - fieldsArray.forEach(field => { - projection[field] = 1; - }); - } - - if( skipFields !== "none" ) { - skipFields.forEach(field=>{ - projection[field] = 0; - }); - } - - let tasks = - await database.models.projectTemplateTasks.find( - queryObject, - projection - ).lean(); - - return resolve(tasks); - - } catch (error) { - return reject(error); - } - }); - } - /** * Extract csv information. * @method @@ -119,7 +74,7 @@ module.exports = class ProjectTemplateTasksHelper { } } - let tasksData = await this.taskDocuments( + let tasksData = await projectTemplateTaskService.taskDocuments( filterData, ["_id","children","externalId","projectTemplateId","parentId"] ); @@ -136,7 +91,7 @@ module.exports = class ProjectTemplateTasksHelper { } let projectTemplate = - await projectTemplatesHelper.templateDocument({ + await projectTemplateService.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : projectTemplateId },["_id","entityType","externalId"]); @@ -335,7 +290,7 @@ module.exports = class ProjectTemplateTasksHelper { if( !update ) { taskData = - await database.models.projectTemplateTasks.create(allValues); + await projectTemplateTaskService.createTemplateTask(allValues); if ( !taskData._id ) { parsedData.STATUS = CONSTANTS.apiResponses.PROJECT_TEMPLATE_TASKS_NOT_CREATED; @@ -347,7 +302,7 @@ module.exports = class ProjectTemplateTasksHelper { } else { taskData = - await database.models.projectTemplateTasks.findOneAndUpdate({ + await projectTemplateTaskService.findOneAndUpdate({ _id : parsedData._SYSTEM_ID },{ $set : allValues @@ -361,7 +316,7 @@ module.exports = class ProjectTemplateTasksHelper { if( parsedData.hasAParentTask === "YES" ) { let parentTask = - await database.models.projectTemplateTasks.findOneAndUpdate({ + await projectTemplateTaskService.findOneAndUpdate({ externalId : parsedData.parentTaskId },{ $addToSet : { @@ -388,7 +343,7 @@ module.exports = class ProjectTemplateTasksHelper { value : parsedData.parentTaskValue }); - await database.models.projectTemplateTasks.findOneAndUpdate({ + await projectTemplateTaskService.findOneAndUpdate({ _id : taskData._id },{ $set : { @@ -403,7 +358,7 @@ module.exports = class ProjectTemplateTasksHelper { } } - await projectTemplatesHelper.updateProjectTemplateDocument + await projectTemplateService.updateProjectTemplateDocument ( { _id : template._id }, { $addToSet : { tasks : ObjectId(taskData._id) } } @@ -601,7 +556,7 @@ module.exports = class ProjectTemplateTasksHelper { csvData.data.tasks[currentData._SYSTEM_ID].parentId.toString() !== createdTask._parentTaskId.toString() ) { - await database.models.projectTemplateTasks.findOneAndUpdate( + await projectTemplateTaskService.findOneAndUpdate( { _id: csvData.data.tasks[currentData._SYSTEM_ID].parentId }, diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 39618865..65e8b413 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -17,56 +17,12 @@ const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/helper"); const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); +const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); +const projectTemplateTaskService = require(DB_SERVICE_BASE_PATH + "/projectTemplateTask"); +const projectService = require(DB_SERVICE_BASE_PATH + "/projects"); module.exports = class ProjectTemplatesHelper { - /** - * Lists of template. - * @method - * @name templateDocument - * @param {Array} [filterData = "all"] - template filter query. - * @param {Array} [fieldsArray = "all"] - projected fields. - * @param {Array} [skipFields = "none"] - field not to include - * @returns {Array} Lists of template. - */ - - static templateDocument( - filterData = "all", - fieldsArray = "all", - skipFields = "none" - ) { - return new Promise(async (resolve, reject) => { - try { - - let queryObject = (filterData != "all") ? filterData : {}; - let projection = {} - - if (fieldsArray != "all") { - fieldsArray.forEach(field => { - projection[field] = 1; - }); - } - - if( skipFields !== "none" ) { - skipFields.forEach(field=>{ - projection[field] = 0; - }); - } - - let templates = - await database.models.projectTemplates.find( - queryObject, - projection - ).lean(); - - return resolve(templates); - - } catch (error) { - return reject(error); - } - }); - } - /** * Extract csv information. * @method @@ -122,7 +78,7 @@ module.exports = class ProjectTemplatesHelper { if( categoryIds.length > 0 ) { let categories = - await libraryCategoriesHelper.categoryDocuments({ + await projectCategoriesService.categoryDocuments({ externalId : { $in : categoryIds } },["externalId","name"]); @@ -338,13 +294,13 @@ module.exports = class ProjectTemplatesHelper { for ( let template = 0; template < templates.length ; template ++ ) { let currentData = templates[template]; - + let templateData = - await this.templateDocument({ - status : CONSTANTS.common.PUBLISHED, - externalId : currentData.externalId, - isReusable : true - },["_id"]); + await projectTemplateService.templateDocument({ + status : CONSTANTS.common.PUBLISHED, + externalId : currentData.externalId, + isReusable : true + },["_id"]); if( templateData.length > 0 && templateData[0]._id ) { currentData["_SYSTEM_ID"] = @@ -361,10 +317,7 @@ module.exports = class ProjectTemplatesHelper { templateData.createdBy = templateData.updatedBy = templateData.userId = userId; templateData.isReusable = true; - let createdTemplate = - await database.models.projectTemplates.create( - templateData - ); + let createdTemplate = await projectTemplateService.createTemplate(templateData); if( !createdTemplate._id ) { currentData["_SYSTEM_ID"] = CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; @@ -478,7 +431,7 @@ module.exports = class ProjectTemplatesHelper { } else { const template = - await this.templateDocument({ + await projectTemplateService.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : currentData._SYSTEM_ID, status : CONSTANTS.common.PUBLISHED @@ -498,15 +451,15 @@ module.exports = class ProjectTemplatesHelper { templateData.updatedBy = userId; let projectTemplateUpdated = - await database.models.projectTemplates.findOneAndUpdate({ + await projectTemplateService.findOneAndUpdate({ _id : currentData._SYSTEM_ID },{ $set : templateData },{ - new : true + new : true }); - if( !projectTemplateUpdated._id ) { + if( !projectTemplateUpdated || !projectTemplateUpdated._id ) { currentData["UPDATE_STATUS"] = constants.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED; } @@ -591,7 +544,7 @@ module.exports = class ProjectTemplatesHelper { try { let projectTemplateData = - await this.templateDocument({ + await projectTemplateService.templateDocument({ status : CONSTANTS.common.PUBLISHED, externalId : templateId, isReusable : true @@ -667,7 +620,7 @@ module.exports = class ProjectTemplatesHelper { newProjectTemplate.isReusable = false; let duplicateTemplateDocument = - await database.models.projectTemplates.create( + await projectTemplateService.createTemplate( _.omit(newProjectTemplate, ["_id"]) ); @@ -743,7 +696,7 @@ module.exports = class ProjectTemplatesHelper { } let templateData = - await this.templateDocument({ + await projectTemplateService.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : templateId, isReusable : true @@ -794,7 +747,7 @@ module.exports = class ProjectTemplatesHelper { updateRating.noOfRatings = calculateRating.noOfRatings; ratingUpdated = - await database.models.projectTemplates.findOneAndUpdate({ + await projectTemplateService.findOneAndUpdate({ _id : templateId },{ $set : updateRating @@ -856,10 +809,14 @@ module.exports = class ProjectTemplatesHelper { await Promise.all(taskIds.map(async taskId => { - let taskData = await database.models.projectTemplateTasks.findOne( + let taskData = await projectTemplateTaskService.taskDocuments( { _id : taskId - }).lean(); + }); + + if(taskData && taskData.length > 0){ + taskData = taskData[0]; + } if(taskData){ //duplicate task @@ -868,7 +825,7 @@ module.exports = class ProjectTemplatesHelper { newProjectTemplateTask.projectTemplateExternalId = duplicateTemplateExternalId; newProjectTemplateTask.externalId = taskData.externalId +"-"+ UTILS.epochTime(); duplicateTemplateTask = - await database.models.projectTemplateTasks.create( + await projectTemplateTaskService.createTemplateTask( _.omit(newProjectTemplateTask, ["_id"]) ); newTaskId.push(duplicateTemplateTask._id); @@ -879,10 +836,14 @@ module.exports = class ProjectTemplatesHelper { if(childTaskIds && childTaskIds.length > 0){ await Promise.all(childTaskIds.map(async childtaskId => { - let childTaskData = await database.models.projectTemplateTasks.findOne( - { - _id : childtaskId - }).lean(); + let childTaskData = await projectTemplateTaskService.taskDocuments( + { + _id : childtaskId + }); + + if(childTaskData && childTaskData.length > 0){ + childTaskData = childTaskData[0]; + } if(childTaskData){ newProjectTemplateChildTask = {...childTaskData}; @@ -891,7 +852,7 @@ module.exports = class ProjectTemplatesHelper { newProjectTemplateChildTask.parentId = duplicateTemplateTask._id; newProjectTemplateChildTask.externalId = childTaskData.externalId +"-"+ UTILS.epochTime(); duplicateChildTemplateTask = - await database.models.projectTemplateTasks.create( + await projectTemplateTaskService.createTemplateTask( _.omit(newProjectTemplateChildTask, ["_id"]) ); @@ -900,7 +861,7 @@ module.exports = class ProjectTemplatesHelper { })) if(childTaskIdArray && childTaskIdArray.length > 0){ - let updateTaskData = await database.models.projectTemplateTasks.findOneAndUpdate( + let updateTaskData = projectTemplateTaskService.updateTaskDocument( { _id : duplicateTemplateTask._id }, @@ -908,7 +869,7 @@ module.exports = class ProjectTemplatesHelper { $set : { children : childTaskIdArray } - }).lean(); + }) } } } @@ -919,7 +880,7 @@ module.exports = class ProjectTemplatesHelper { if(newTaskId && newTaskId.length > 0){ - updateDuplicateTemplate = await database.models.projectTemplates.findOneAndUpdate( + updateDuplicateTemplate = await projectTemplateService.findOneAndUpdate( { _id : duplicateTemplateId }, @@ -927,7 +888,7 @@ module.exports = class ProjectTemplatesHelper { $set : { tasks : newTaskId } - }).lean(); + }) } return resolve( @@ -941,53 +902,6 @@ module.exports = class ProjectTemplatesHelper { }) } - /** - * Update projectTemplates document. - * @method - * @name updateProjectTemplateDocument - * @param {Object} query - query to find document - * @param {Object} updateObject - fields to update - * @returns {String} - message. - */ - - static updateProjectTemplateDocument(query= {}, updateObject= {}) { - return new Promise(async (resolve, reject) => { - try { - - if (Object.keys(query).length == 0) { - throw new Error(CONSTANTS.apiResponses.UPDATE_QUERY_REQUIRED) - } - - if (Object.keys(updateObject).length == 0) { - throw new Error (CONSTANTS.apiResponses.UPDATE_OBJECT_REQUIRED) - } - - let updateResponse = await database.models.projectTemplates.updateOne - ( - query, - updateObject - ) - - if (updateResponse.nModified == 0) { - throw new Error(CONSTANTS.apiResponses.FAILED_TO_UPDATE) - } - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, - data: true - }); - - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: false - }); - } - }); - } - /** * Templates list. * @method @@ -1000,7 +914,7 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { - let templateData = await this.templateDocument({ + let templateData = await projectTemplateService.templateDocument({ externalId : { $in : externalIds } },["title","metaInformation.goal","externalId"]); @@ -1045,7 +959,7 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { - let templateData = await this.templateDocument({ + let templateData = await projectTemplateService.templateDocument({ externalId : templateId },"all", [ @@ -1085,15 +999,13 @@ module.exports = class ProjectTemplatesHelper { templateData[0].projectId = ""; - let project = await database.models.projects.findOne({ + let project = await projectService.projectDocument({ userId : userId, projectTemplateId : templateData[0]._id - },{ - _id : 1 - }).lean(); + },["_id"]); - if( project && project._id ) { - templateData[0].projectId = project._id; + if(project && project.length > 0){ + templateData[0].projectId = project[0]._id; } } @@ -1122,7 +1034,7 @@ module.exports = class ProjectTemplatesHelper { try { const templateDocument = - await this.templateDocument({ + await projectTemplateService.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : templateId },["tasks"]); @@ -1130,31 +1042,27 @@ module.exports = class ProjectTemplatesHelper { let tasks = []; if( templateDocument[0].tasks ) { - - tasks = await database.models.projectTemplateTasks.find({ + + let findQuery = { _id : { $in : templateDocument[0].tasks }, parentId : { $exists : false } - },{ - "projectTemplateId" : 0, - "__v" : 0, - "projectTemplateExternalId" : 0 - }).lean(); + } + + tasks = await projectTemplateService.templateDocument(findQuery,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); for( let task = 0 ; task < tasks.length ; task ++ ) { if( tasks[task].children && tasks[task].children.length > 0 ) { - - let subTasks = await database.models.projectTemplateTasks.find({ + + let subTaskQuery = { _id : { $in : tasks[task].children } - },{ - "projectTemplateId" : 0, - "__v" : 0, - "projectTemplateExternalId" : 0 - }).lean(); + } + + let subTasks = await projectTemplateTaskService.taskDocuments(subTaskQuery, ["projectTemplateId","__v","projectTemplateExternalId"]); tasks[task].children = subTasks; } diff --git a/module/reports/helper.js b/module/reports/helper.js index 26d670db..e8ba55f7 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -9,6 +9,7 @@ const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); const dhitiService = require(GENERICS_FILES_PATH + "/services/dhiti"); +const projectService = require(DB_SERVICE_BASE_PATH + "/projects"); const moment = require('moment'); @@ -64,7 +65,7 @@ module.exports = class ReportsHelper { { "tasks": { $elemMatch: { isDeleted: { $ne: true },syncedAt: { $gte: new Date(startFrom), $lte: new Date(endOf) } } } }, ] - const projectDetails = await userProjectsHelper.projectDocument( + const projectDetails = await projectService.projectDocument( query, ["programId","programInformation.name", "entityInformation.name", "taskReport", "status", "tasks", "categories"], [] @@ -486,7 +487,7 @@ module.exports = class ReportsHelper { query['programId'] = ObjectId(programId); } - const projectDetails = await userProjectsHelper.projectDocument( + const projectDetails = await projectService.projectDocument( query, ["title", "taskReport", diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 8c09a954..a0c4c9fc 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -14,6 +14,10 @@ const projectTemplateTasksHelper = require(MODULES_BASE_PATH + "/project/templat const { v4: uuidv4 } = require('uuid'); const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); const dhitiService = require(GENERICS_FILES_PATH + "/services/dhiti"); +const projectService = require(DB_SERVICE_BASE_PATH + "/projects"); +const projectCategoriesService = require(DB_SERVICE_BASE_PATH + "/projectCategories"); +const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); +const projectTemplateTaskService = require(DB_SERVICE_BASE_PATH + "/projectTemplateTask"); /** * UserProjectsHelper @@ -22,53 +26,6 @@ const dhitiService = require(GENERICS_FILES_PATH + "/services/dhiti"); module.exports = class UserProjectsHelper { - /** - * Lists of projects. - * @method - * @name projectDocument - * @param {Array} [filterData = "all"] - project filter query. - * @param {Array} [fieldsArray = "all"] - projected fields. - * @param {Array} [skipFields = "none"] - field not to include - * @returns {Array} Lists of projects. - */ - - static projectDocument( - filterData = "all", - fieldsArray = "all", - skipFields = "none" - ) { - return new Promise(async (resolve, reject) => { - try { - - let queryObject = (filterData != "all") ? filterData : {}; - let projection = {} - - if (fieldsArray != "all") { - fieldsArray.forEach(field => { - projection[field] = 1; - }); - } - - if (skipFields !== "none") { - skipFields.forEach(field => { - projection[field] = 0; - }); - } - - let templates = - await database.models.projects.find( - queryObject, - projection - ).lean(); - - return resolve(templates); - - } catch (error) { - return reject(error); - } - }); - } - /** * Projects boolean data. * @method @@ -141,7 +98,7 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - const userProject = await this.projectDocument({ + const userProject = await projectService.projectDocument({ _id: projectId, userId: userId }, [ @@ -363,7 +320,7 @@ module.exports = class UserProjectsHelper { } let projectUpdated = - await database.models.projects.findOneAndUpdate( + await projectService.findOneAndUpdate( { _id: userProject[0]._id }, @@ -510,7 +467,7 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - const projectDetails = await this.projectDocument({ + const projectDetails = await projectService.projectDocument({ _id: projectId, userId: userId }, "all", @@ -540,7 +497,7 @@ module.exports = class UserProjectsHelper { if (Object.keys(userRoleInformtion).length > 0) { if (!projectDetails[0].userRoleInformtion || !Object.keys(projectDetails[0].userRoleInformtion).length > 0) { - await database.models.projects.findOneAndUpdate({ + await projectService.findOneAndUpdate({ _id: projectId },{ $set: {userRoleInformtion: userRoleInformtion} @@ -641,7 +598,7 @@ module.exports = class UserProjectsHelper { ); let result = - await database.models.projects.aggregate(aggregateData); + await projectService.getAggregate(aggregateData); return resolve({ success: true, @@ -713,7 +670,7 @@ module.exports = class UserProjectsHelper { aggregatedData.push(projectData); let projects = - await database.models.projects.aggregate(aggregatedData); + await projectService.getAggregate(aggregatedData); return resolve({ success: true, @@ -817,7 +774,7 @@ module.exports = class UserProjectsHelper { }); const tasksUpdated = - await database.models.projects.findOneAndUpdate({ + await projectService.findOneAndUpdate({ _id: projectId, "tasks._id": taskId }, { $set: update }); @@ -844,7 +801,7 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - let project = await this.projectDocument( + let project = await projectService.projectDocument( { "_id": projectId, "tasks._id": taskId @@ -909,7 +866,7 @@ module.exports = class UserProjectsHelper { currentTask.solutionDetails.programId; } - await database.models.projects.findOneAndUpdate({ + await projectService.findOneAndUpdate({ "_id": projectId, "tasks._id": taskId }, { @@ -946,127 +903,6 @@ module.exports = class UserProjectsHelper { }) } - /** - * User assigned project creation data. - * @method - * @name userAssignedProjectCreation - * @param {String} templateId - Project template id. - * @param {String} userId - Logged in user id. - * @param {String} userToken - Logged in user token. - * @returns {String} - message. - */ - - static userAssignedProjectCreation(templateId, userId, userToken) { - return new Promise(async (resolve, reject) => { - try { - - const projectTemplateData = - await projectTemplatesHelper.templateDocument({ - status: CONSTANTS.common.PUBLISHED, - _id: templateId, - isReusable: false - }, "all", - [ - "ratings", - "noOfRatings", - "averageRating" - ]); - - if (!projectTemplateData.length > 0) { - throw { - message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - let result = { ...projectTemplateData[0] }; - - result.projectTemplateId = result._id; - result.projectTemplateExternalId = result.externalId; - result.userId = userId; - result.createdBy = userId; - result.updatedBy = userId; - - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken, - userId - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - result.createdFor = - userOrganisations.data.createdFor; - - result.rootOrganisations = - userOrganisations.data.rootOrganisations; - - result.assesmentOrObservationTask = false; - - if (projectTemplateData[0].tasks && projectTemplateData[0].tasks.length > 0) { - - const tasksAndSubTasks = - await projectTemplatesHelper.tasksAndSubTasks( - projectTemplateData[0]._id - ); - - if (tasksAndSubTasks.length > 0) { - - result.tasks = _projectTask(tasksAndSubTasks); - - result.tasks.forEach(task => { - if ( - task.type === CONSTANTS.common.ASSESSMENT || - task.type === CONSTANTS.common.OBSERVATION - ) { - result.assesmentOrObservationTask = true; - } - }); - - - let taskReport = { - total: result.tasks.length - }; - - result.tasks.forEach(task => { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - }); - - result["taskReport"] = taskReport; - - } - } - - delete result._id; - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, - data: result - }); - - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); - } - }); - } - /** * Creation of user targeted projects. * @method @@ -1090,7 +926,7 @@ module.exports = class UserProjectsHelper { if( templateId !== "" ) { let templateDocuments = - await projectTemplatesHelper.templateDocument({ + await projectTemplateService.templateDocument({ "externalId" : templateId, "isReusable" : false, "solutionId" : { $exists : true } @@ -1112,7 +948,7 @@ module.exports = class UserProjectsHelper { if (projectId === "") { - const projectDetails = await this.projectDocument({ + const projectDetails = await projectService.projectDocument({ solutionId: solutionId, userId: userId }, ["_id"]); @@ -1254,7 +1090,7 @@ module.exports = class UserProjectsHelper { projectCreation.data.lastDownloadedAt = new Date(); projectCreation.data.userRoleInformtion = userRoleInformation; - let project = await database.models.projects.create(projectCreation.data); + let project = await projectService.createProject(projectCreation.data); projectId = project._id; } } @@ -1299,7 +1135,7 @@ module.exports = class UserProjectsHelper { try { const projectTemplateData = - await projectTemplatesHelper.templateDocument({ + await projectTemplateService.templateDocument({ status: CONSTANTS.common.PUBLISHED, _id: templateId, isReusable: false @@ -1550,7 +1386,7 @@ module.exports = class UserProjectsHelper { createProject.userRoleInformtion = data.profileInformation; } - let userProject = await database.models.projects.create( + let userProject = await projectService.createProject( createProject ); @@ -1610,7 +1446,7 @@ module.exports = class UserProjectsHelper { if (!taskIds.length ) { - projectDocument = await this.projectDocument + projectDocument = await projectService.projectDocument ( query, [ @@ -1642,7 +1478,7 @@ module.exports = class UserProjectsHelper { }} }}] - projectDocument = await database.models.projects.aggregate(aggregateData); + projectDocument = await projectService.getAggregate(aggregateData); } if (!projectDocument.length) { @@ -1856,7 +1692,7 @@ module.exports = class UserProjectsHelper { filterQuery["programId"] = programId; } - let importedProjects = await this.projectDocument( + let importedProjects = await projectService.projectDocument( filterQuery, [ "solutionInformation", @@ -2097,7 +1933,7 @@ function _projectCategories(categories) { if (categoryIds.length > 0) { categoryData = - await libraryCategoriesHelper.categoryDocuments({ + await projectCategoriesService.categoryDocuments({ _id: { $in: categoryIds } }, ["name", "externalId"]); @@ -2223,7 +2059,7 @@ function _assessmentDetails(assessmentData) { if (assessmentData.project) { let templateTasks = - await projectTemplateTasksHelper.taskDocuments({ + await projectTemplateTaskService.taskDocuments({ externalId: assessmentData.project.taskId }, ["_id"]) @@ -2343,7 +2179,7 @@ function _observationDetails(observationData) { if (observationData.project) { let templateTasks = - await projectTemplateTasksHelper.taskDocuments({ + await projectTemplateTaskService.taskDocuments({ externalId: observationData.project.taskId }, ["_id"]) diff --git a/services/projectCategories.js b/services/projectCategories.js new file mode 100644 index 00000000..df39d226 --- /dev/null +++ b/services/projectCategories.js @@ -0,0 +1,98 @@ +/** + * name : projectCategories.js + * author : Priyanka + * created-date : 16-July-2020 + * Description : Project categories helper for DB interactions. + */ + +// Dependencies + +/** + * ProjectCategoriesService + * @class +*/ + +module.exports = class ProjectCategoriesService { + + /** + * Library project categories documents. + * @method + * @name categoryDocuments + * @param {Object} [findQuery = "all"] - filtered data. + * @param {Array} [fields = "all"] - projected data. + * @param {Array} [skipFields = "none"] - fields to skip. + * @returns {Array} - Library project categories data. + */ + + static categoryDocuments( + findQuery = "all", + fields = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + + try { + + let queryObject = {}; + + if (findQuery != "all") { + queryObject = findQuery; + } + + let projection = {}; + + if (fields != "all") { + fields.forEach(element => { + projection[element] = 1; + }); + } + + if (skipFields != "none") { + skipFields.forEach(element => { + projection[element] = 0; + }); + } + + let projectCategoriesData = + await database.models.projectCategories.find( + queryObject, + projection + ).lean(); + + return resolve(projectCategoriesData); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * update Many project categories documents. + * @method + * @name updateMany + * @param {Object} [filterQuery] - filtered Query. + * @param {Object} [updateData] - update data. + * @returns {Array} - Library project categories data. + */ + + static updateMany(filterQuery, updateData) { + return new Promise(async (resolve, reject) => { + + try { + + let updatedCategories = + await database.models.projectCategories.updateMany( + filterQuery, + updateData + ); + + return resolve(updatedCategories); + + } catch (error) { + return reject(error); + } + }); + } + +}; diff --git a/services/projectTemplateTask.js b/services/projectTemplateTask.js new file mode 100644 index 00000000..7122d2d4 --- /dev/null +++ b/services/projectTemplateTask.js @@ -0,0 +1,156 @@ +/** + * name : projectTemplateTask.js + * author : Priyanka + * created-date : 16-July-2020 + * Description : Project Templates helper for DB interactions. + */ + +// Dependencies + +/** + * ProjectTemplateTaskService + * @class +*/ + +module.exports = class ProjectTemplateTaskService { + + /** + * Lists of template tasks. + * @method + * @name taskDocuments + * @param {Array} [filterData = "all"] - template filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} Lists of template. + */ + + static taskDocuments( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + + let templateTasks = + await database.models.projectTemplateTasks.find( + queryObject, + projection + ).lean(); + + return resolve(templateTasks); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Create project template task. + * @method + * @name createTemplateTask + * @param {Object} [templateData] - template task Data. + * @returns {Object} - Project template task data. + */ + + static createTemplateTask(templateData) { + return new Promise(async (resolve, reject) => { + + try { + + let templateTask = await database.models.projectTemplateTasks.create(templateData); + return resolve(templateTask); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Update projectTemplateTask document. + * @method + * @name updateTaskDocument + * @param {Object} query - query to find document + * @param {Object} updateObject - fields to update + * @returns {String} - message. + */ + + static updateTaskDocument(query= {}, updateObject= {}) { + return new Promise(async (resolve, reject) => { + try { + + if (Object.keys(query).length == 0) { + throw new Error(CONSTANTS.apiResponses.UPDATE_QUERY_REQUIRED) + } + + if (Object.keys(updateObject).length == 0) { + throw new Error (CONSTANTS.apiResponses.UPDATE_OBJECT_REQUIRED) + } + + let updateResponse = await database.models.projectTemplateTasks.updateOne + ( + query, + updateObject + ) + + if (updateResponse.nModified == 0) { + throw new Error(CONSTANTS.apiResponses.FAILED_TO_UPDATE) + } + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, + data: true + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: false + }); + } + }); + } + + /** + * Update project templates task documents. + * @method + * @name findOneAndUpdate + * @param {Object} [filterQuery] - filtered Query. + * @param {Object} [updateData] - update data. + * @returns {Object} - Project templates task data. + */ + + static findOneAndUpdate(findQuery,UpdateObject, returnData = {}) { + return new Promise(async (resolve, reject) => { + + try { + + let templateTask = await database.models.projectTemplateTasks.findOneAndUpdate(findQuery,UpdateObject, returnData); + return resolve(templateTask); + + } catch (error) { + return reject(error); + } + }); + } + +}; diff --git a/services/projectTemplates.js b/services/projectTemplates.js new file mode 100644 index 00000000..0e595431 --- /dev/null +++ b/services/projectTemplates.js @@ -0,0 +1,178 @@ +/** + * name : projectTemplates.js + * author : Priyanka + * created-date : 16-July-2020 + * Description : Project Templates helper for DB interactions. + */ + +// Dependencies + +/** + * ProjectTemplateService + * @class +*/ + +module.exports = class ProjectTemplateService { + + /** + * Project templates documents. + * @method + * @name getAggregate + * @param {Object} [aggregateData] - aggregate Data. + * @returns {Array} - Project templates data. + */ + + static getAggregate(aggregateData) { + return new Promise(async (resolve, reject) => { + + try { + + let projectTemplatesData = await database.models.projectTemplates.aggregate(aggregateData); + return resolve(projectTemplatesData); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Lists of template. + * @method + * @name templateDocument + * @param {Array} [filterData = "all"] - template filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} Lists of template. + */ + + static templateDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + + let templates = + await database.models.projectTemplates.find( + queryObject, + projection + ).lean(); + + return resolve(templates); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Create project templates documents. + * @method + * @name createTemplate + * @param {Object} [templateData] - template Data. + * @returns {Array} - Project templates data. + */ + + static createTemplate(templateData) { + return new Promise(async (resolve, reject) => { + + try { + + let projectTemplate = await database.models.projectTemplates.create(templateData); + return resolve(projectTemplate); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Update project templates documents. + * @method + * @name findOneAndUpdate + * @param {Object} [filterQuery] - filtered Query. + * @param {Object} [updateData] - update data. + * @returns {Array} - Project templates data. + */ + + static findOneAndUpdate(findQuery,UpdateObject, returnData = {}) { + return new Promise(async (resolve, reject) => { + + try { + + let projectTemplate = await database.models.projectTemplates.findOneAndUpdate(findQuery,UpdateObject, returnData); + return resolve(projectTemplate); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Update projectTemplates document. + * @method + * @name updateProjectTemplateDocument + * @param {Object} query - query to find document + * @param {Object} updateObject - fields to update + * @returns {String} - message. + */ + + static updateProjectTemplateDocument(query= {}, updateObject= {}) { + return new Promise(async (resolve, reject) => { + try { + + if (Object.keys(query).length == 0) { + throw new Error(CONSTANTS.apiResponses.UPDATE_QUERY_REQUIRED) + } + + if (Object.keys(updateObject).length == 0) { + throw new Error (CONSTANTS.apiResponses.UPDATE_OBJECT_REQUIRED) + } + + let updateResponse = await database.models.projectTemplates.updateOne + ( + query, + updateObject + ) + + if (updateResponse.nModified == 0) { + throw new Error(CONSTANTS.apiResponses.FAILED_TO_UPDATE) + } + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, + data: true + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: false + }); + } + }); + } + +}; diff --git a/services/projects.js b/services/projects.js new file mode 100644 index 00000000..e533c68e --- /dev/null +++ b/services/projects.js @@ -0,0 +1,131 @@ +/** + * name : projects.js + * author : Priyanka + * created-date : 16-July-2020 + * Description : Project categories helper for DB interactions. + */ + +// Dependencies + +/** + * ProjectService + * @class +*/ + +module.exports = class ProjectService { + + /** + * Lists of projects document. + * @method + * @name projectDocument + * @param {Array} [filterData = "all"] - project filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} Lists of projects. + */ + + static projectDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + + let projects = + await database.models.projects.find( + queryObject, + projection + ).lean(); + + return resolve(projects); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Get Aggregate of Project documents. + * @method + * @name getAggregate + * @param {Object} [aggregateData] - aggregate Data. + * @returns {Array} - Project data. + */ + + static getAggregate(aggregateData) { + return new Promise(async (resolve, reject) => { + + try { + + let projectDocuments = await database.models.projects.aggregate(aggregateData); + return resolve(projectDocuments); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Update project documents. + * @method + * @name findOneAndUpdate + * @param {Object} [filterQuery] - filtered Query. + * @param {Object} [updateData] - update data. + * @returns {Object} - Project data. + */ + + static findOneAndUpdate(findQuery,UpdateObject, returnData = {}) { + return new Promise(async (resolve, reject) => { + + try { + + let projectDocument = await database.models.projects.findOneAndUpdate(findQuery,UpdateObject, returnData); + return resolve(projectDocument); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Create project documents. + * @method + * @name createProject + * @param {Object} [projectData] - project Data. + * @returns {Array} - Project data. + */ + + static createProject(projectData) { + return new Promise(async (resolve, reject) => { + + try { + + let projectDocument = await database.models.projects.create(projectData); + return resolve(projectDocument); + + } catch (error) { + return reject(error); + } + }); + } + +}; From d971316d3527654584bdc15c4338a36d238d0524 Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Thu, 2 Sep 2021 13:24:13 +0530 Subject: [PATCH 008/373] Removed rootorganisations and created for --- controllers/v1/solutions.js | 2 - controllers/v1/userProjects.js | 2 - generics/constants/endpoints.js | 1 - generics/services/kendra.js | 61 +------------------ models/projects.js | 8 --- module/project/templates/helper.js | 2 - module/solutions/validator/v1.js | 2 - module/userProjects/helper.js | 95 +----------------------------- 8 files changed, 2 insertions(+), 171 deletions(-) diff --git a/controllers/v1/solutions.js b/controllers/v1/solutions.js index 107278ad..1254b978 100644 --- a/controllers/v1/solutions.js +++ b/controllers/v1/solutions.js @@ -16,8 +16,6 @@ module.exports = class Solutions { * @apiGroup Solutions * @apiParamExample {json} Request-Body: * { - * "createdFor" : ["01305447637218918413"], - * "rootOrganisations" : ["01305447637218918413"], "programExternalId" : "AMAN_TEST_123-1607937244986", "entityType" : "school", "externalId" : "IMPROVEMENT-PROJECT-TEST-SOLUTION", diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 31fd1fbe..51fe289c 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -400,7 +400,6 @@ module.exports = class UserProjects extends Abstract { "status": 200, "result": { "userId": "01c04166-a65e-4e92-a87b-a9e4194e771d", - "createdFor": [], "isDeleted": false, "categories": [ { @@ -498,7 +497,6 @@ module.exports = class UserProjects extends Abstract { } ], "updatedBy": "01c04166-a65e-4e92-a87b-a9e4194e771d", - "rootOrganisations": [], "_id": "5f731d68920a8c3e092e6e4c", "deleted": false, "name": "Test-2", diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index cb586fbb..ace4f25d 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -22,7 +22,6 @@ module.exports = { USER_PRIVATE_PROGRAMS : "/v1/users/privatePrograms", UPDATE_SOLUTIONS : "/v1/solutions/updateSolutions", LIST_PROGRAMS : "/v1/programs/list", - GET_USER_ORGANISATIONS : "/v1/users/getUserOrganisationsAndRootOrganisations", PRESIGNED_GCP_URL : "/v1/cloud-services/gcp/preSignedUrls", // Kendra service PRESIGNED_AWS_URL : "/v1/cloud-services/aws/preSignedUrls", // Kendra service PRESIGNED_AZURE_URL : "/v1/cloud-services/azure/preSignedUrls", // Kendra service, diff --git a/generics/services/kendra.js b/generics/services/kendra.js index 9919031e..3a0ecfe5 100644 --- a/generics/services/kendra.js +++ b/generics/services/kendra.js @@ -717,64 +717,6 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution }) } -/** - * Update solution - * @function - * @name getUserOrganisationsAndRootOrganisations - * @param {String} token - Logged in user token. - * @param {String} userId - User id. - * @returns {JSON} - Update solutions. -*/ - -const getUserOrganisationsAndRootOrganisations = function ( token,userId = "" ) { - return new Promise(async (resolve, reject) => { - try { - - let url = - KENDRA_URL + - CONSTANTS.endpoints.GET_USER_ORGANISATIONS; - - if( userId !== "" ) { - url = url + "/" + userId; - } - - const options = { - headers : { - "content-type": "application/json", - "x-authenticated-user-token" : token - } - }; - - request.post(url,options,kendraCallback); - - function kendraCallback(err, data) { - - let result = { - success : true - }; - - if (err) { - result.success = false; - } else { - - let response = JSON.parse(data.body); - if( response.status === HTTP_STATUS_CODE['ok'].status ) { - result["data"] = response.result; - } else { - result.success = false; - } - - } - - return resolve(result); - } - - } catch (error) { - return reject(error); - } - }) -} - module.exports = { entityTypesDocuments : entityTypesDocuments, rolesDocuments : rolesDocuments, @@ -788,7 +730,6 @@ module.exports = { createSolution: createSolution, solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, - getDownloadableUrl : getDownloadableUrl, - getUserOrganisationsAndRootOrganisations : getUserOrganisationsAndRootOrganisations + getDownloadableUrl : getDownloadableUrl }; diff --git a/models/projects.js b/models/projects.js index 3fe782c7..b6f60e81 100644 --- a/models/projects.js +++ b/models/projects.js @@ -28,10 +28,6 @@ module.exports = { default : "", index: true }, - createdFor : { - type : Array, - default : [] - }, status : { type : String, default : "notStarted", @@ -81,10 +77,6 @@ module.exports = { }, startDate: Date, endDate: Date, - rootOrganisations : { - type : [String], - default : [] - }, learningResources : { type : Array, default : [] diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 39618865..e62e3601 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1053,8 +1053,6 @@ module.exports = class ProjectTemplatesHelper { "noOfRatings", "averageRating", "parentTemplateId", - "createdFor", - "rootOrganisations", "userId", "createdBy", "updatedBy", diff --git a/module/solutions/validator/v1.js b/module/solutions/validator/v1.js index 7eeacba6..2e4258cc 100644 --- a/module/solutions/validator/v1.js +++ b/module/solutions/validator/v1.js @@ -10,8 +10,6 @@ module.exports = (req) => { let solutionsValidator = { create : function () { - req.checkBody('createdFor').exists().withMessage("required organisation created for id"); - req.checkBody('rootOrganisations').exists().withMessage("required root organisations id"); req.checkBody('programExternalId').exists().withMessage("required program externalId"); req.checkBody('entityType').exists().withMessage("required entity type"); req.checkBody('externalId').exists().withMessage("required solution externalId"); diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index d565fb3d..309d72f1 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -90,9 +90,7 @@ module.exports = class UserProjectsHelper { }, "all", [ "createdBy", "updatedBy", - "rootOrganisations", "taskReport", - "createdFor", "projectTemplateId", "projectTemplateExternalId", "__v" @@ -721,21 +719,6 @@ module.exports = class UserProjectsHelper { ) } - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - libraryProjects.data.createdFor = userOrganisations.data.createdFor; - libraryProjects.data.rootOrganisations = userOrganisations.data.rootOrganisations; - libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; libraryProjects.data.lastDownloadedAt = new Date(); libraryProjects.data.status = CONSTANTS.common.NOT_STARTED_STATUS; @@ -795,30 +778,11 @@ module.exports = class UserProjectsHelper { try { let creationData = { - lastDownloadedAt: new Date(), - createdFor: [], - rootOrganisations: [] + lastDownloadedAt: new Date() } creationData["userId"] = creationData["createdBy"] = creationData["updatedBy"] = userId; - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - if (userOrganisations.data) { - creationData.createdFor = userOrganisations.data.createdFor; - creationData.rootOrganisations = userOrganisations.data.rootOrganisations; - } - let userProject = await database.models.projects.create( creationData ); @@ -1235,8 +1199,6 @@ module.exports = class UserProjectsHelper { }, "all", [ "taskReport", - "createdFor", - "rootOrganisations", "projectTemplateId", "projectTemplateExternalId", "userId", @@ -1757,25 +1719,6 @@ module.exports = class UserProjectsHelper { result.createdBy = userId; result.updatedBy = userId; - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken, - userId - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - result.createdFor = - userOrganisations.data.createdFor; - - result.rootOrganisations = - userOrganisations.data.rootOrganisations; - result.assesmentOrObservationTask = false; if (projectTemplateData[0].tasks && projectTemplateData[0].tasks.length > 0) { @@ -2251,25 +2194,6 @@ module.exports = class UserProjectsHelper { result.createdBy = userId; result.updatedBy = userId; - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken, - userId - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - result.createdFor = - userOrganisations.data.createdFor; - - result.rootOrganisations = - userOrganisations.data.rootOrganisations; - result.createdAt = new Date(); result.updatedAt = new Date(); @@ -2355,23 +2279,6 @@ module.exports = class UserProjectsHelper { createProject["userId"] = createProject["createdBy"] = createProject["updatedBy"] = userId; - let userOrganisations = - await kendraService.getUserOrganisationsAndRootOrganisations( - userToken - ); - - if (!userOrganisations.success) { - throw { - message: CONSTANTS.apiResponses.USER_ORGANISATION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - if (userOrganisations.data) { - createProject.createdFor = userOrganisations.data.createdFor; - createProject.rootOrganisations = userOrganisations.data.rootOrganisations; - } - let projectData = await _projectData(data); if (projectData && projectData.success == true) { createProject = _.merge(createProject, projectData.data); From 02a4143ea9bf476182b55b4eac3fd701cfdb0b2d Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 15 Sep 2021 11:54:37 +0530 Subject: [PATCH 009/373] name change --- config/globals.js | 2 +- {services => databaseQueries}/projectCategories.js | 2 +- {services => databaseQueries}/projectTemplateTask.js | 2 +- {services => databaseQueries}/projectTemplates.js | 2 +- {services => databaseQueries}/projects.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename {services => databaseQueries}/projectCategories.js (98%) rename {services => databaseQueries}/projectTemplateTask.js (99%) rename {services => databaseQueries}/projectTemplates.js (99%) rename {services => databaseQueries}/projects.js (99%) diff --git a/config/globals.js b/config/globals.js index 4c6a458a..75b43d09 100644 --- a/config/globals.js +++ b/config/globals.js @@ -15,7 +15,7 @@ module.exports = function () { global.async = require("async"); global.PROJECT_ROOT_DIRECTORY = path.join(__dirname, '..'); global.MODULES_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/module"; - global.DB_SERVICE_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/services"; + global.DB_SERVICE_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/databaseQueries"; global.GENERICS_FILES_PATH = PROJECT_ROOT_DIRECTORY + "/generics"; global.GENERIC_HELPERS_PATH = GENERICS_FILES_PATH + "/helpers"; global._ = require("lodash"); diff --git a/services/projectCategories.js b/databaseQueries/projectCategories.js similarity index 98% rename from services/projectCategories.js rename to databaseQueries/projectCategories.js index df39d226..08541430 100644 --- a/services/projectCategories.js +++ b/databaseQueries/projectCategories.js @@ -1,7 +1,7 @@ /** * name : projectCategories.js * author : Priyanka - * created-date : 16-July-2020 + * created-date : 01-Sep-2021 * Description : Project categories helper for DB interactions. */ diff --git a/services/projectTemplateTask.js b/databaseQueries/projectTemplateTask.js similarity index 99% rename from services/projectTemplateTask.js rename to databaseQueries/projectTemplateTask.js index 7122d2d4..97809061 100644 --- a/services/projectTemplateTask.js +++ b/databaseQueries/projectTemplateTask.js @@ -1,7 +1,7 @@ /** * name : projectTemplateTask.js * author : Priyanka - * created-date : 16-July-2020 + * created-date : 01-Sep-2021 * Description : Project Templates helper for DB interactions. */ diff --git a/services/projectTemplates.js b/databaseQueries/projectTemplates.js similarity index 99% rename from services/projectTemplates.js rename to databaseQueries/projectTemplates.js index 0e595431..89ecc591 100644 --- a/services/projectTemplates.js +++ b/databaseQueries/projectTemplates.js @@ -1,7 +1,7 @@ /** * name : projectTemplates.js * author : Priyanka - * created-date : 16-July-2020 + * created-date : 01-Sep-2021 * Description : Project Templates helper for DB interactions. */ diff --git a/services/projects.js b/databaseQueries/projects.js similarity index 99% rename from services/projects.js rename to databaseQueries/projects.js index e533c68e..6114abb0 100644 --- a/services/projects.js +++ b/databaseQueries/projects.js @@ -1,7 +1,7 @@ /** * name : projects.js * author : Priyanka - * created-date : 16-July-2020 + * created-date : 01-Sep-2021 * Description : Project categories helper for DB interactions. */ From 91a85f20562e6ea54d3e0c6f102040d98e0a438e Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 17 Sep 2021 10:06:17 +0530 Subject: [PATCH 010/373] Pr changes --- config/globals.js | 2 +- databaseQueries/projectCategories.js | 4 +-- databaseQueries/projectTemplateTask.js | 4 +-- databaseQueries/projectTemplates.js | 4 +-- databaseQueries/projects.js | 4 +-- module/library/categories/helper.js | 8 ++--- module/project/templateTasks/helper.js | 20 +++++------ module/project/templates/helper.js | 46 ++++++++++++------------ module/reports/helper.js | 6 ++-- module/userProjects/helper.js | 48 +++++++++++++------------- 10 files changed, 73 insertions(+), 73 deletions(-) diff --git a/config/globals.js b/config/globals.js index 75b43d09..ad63ab7a 100644 --- a/config/globals.js +++ b/config/globals.js @@ -15,7 +15,7 @@ module.exports = function () { global.async = require("async"); global.PROJECT_ROOT_DIRECTORY = path.join(__dirname, '..'); global.MODULES_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/module"; - global.DB_SERVICE_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/databaseQueries"; + global.DB_QUERY_BASE_PATH = PROJECT_ROOT_DIRECTORY + "/databaseQueries"; global.GENERICS_FILES_PATH = PROJECT_ROOT_DIRECTORY + "/generics"; global.GENERIC_HELPERS_PATH = GENERICS_FILES_PATH + "/helpers"; global._ = require("lodash"); diff --git a/databaseQueries/projectCategories.js b/databaseQueries/projectCategories.js index 08541430..7d4a9354 100644 --- a/databaseQueries/projectCategories.js +++ b/databaseQueries/projectCategories.js @@ -8,11 +8,11 @@ // Dependencies /** - * ProjectCategoriesService + * ProjectCategories * @class */ -module.exports = class ProjectCategoriesService { +module.exports = class ProjectCategories { /** * Library project categories documents. diff --git a/databaseQueries/projectTemplateTask.js b/databaseQueries/projectTemplateTask.js index 97809061..ea57ba35 100644 --- a/databaseQueries/projectTemplateTask.js +++ b/databaseQueries/projectTemplateTask.js @@ -8,11 +8,11 @@ // Dependencies /** - * ProjectTemplateTaskService + * ProjectTemplateTask * @class */ -module.exports = class ProjectTemplateTaskService { +module.exports = class ProjectTemplateTask { /** * Lists of template tasks. diff --git a/databaseQueries/projectTemplates.js b/databaseQueries/projectTemplates.js index 89ecc591..fbf6ff0d 100644 --- a/databaseQueries/projectTemplates.js +++ b/databaseQueries/projectTemplates.js @@ -8,11 +8,11 @@ // Dependencies /** - * ProjectTemplateService + * ProjectTemplates * @class */ -module.exports = class ProjectTemplateService { +module.exports = class ProjectTemplates { /** * Project templates documents. diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 6114abb0..a851423b 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -8,11 +8,11 @@ // Dependencies /** - * ProjectService + * Projects * @class */ -module.exports = class ProjectService { +module.exports = class Projects { /** * Lists of projects document. diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index 5f0247c2..22487a02 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -8,8 +8,8 @@ // Dependencies const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); const sessionHelpers = require(GENERIC_HELPERS_PATH+"/sessions"); -const projectCategoriesService = require(DB_SERVICE_BASE_PATH + "/projectCategories"); -const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); +const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); +const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); const moment = require("moment-timezone"); /** @@ -99,7 +99,7 @@ module.exports = class LibraryCategoriesHelper { } }); - let result = await projectTemplateService.getAggregate(aggregateData); + let result = await projectTemplateQueries.getAggregate(aggregateData); if( result[0].data.length > 0 ) { @@ -147,7 +147,7 @@ module.exports = class LibraryCategoriesHelper { return new Promise(async (resolve, reject) => { try { - let categoriesUpdated = await projectCategoriesService.updateMany(filterQuery,updateData); + let categoriesUpdated = await projectCategoriesQueries.updateMany(filterQuery,updateData); if( !categoriesUpdated.ok ) { throw { diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index d0958c52..17b71fde 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -14,8 +14,8 @@ const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/helper"); const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); -const projectTemplateTaskService = require(DB_SERVICE_BASE_PATH + "/projectTemplateTask"); -const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); +const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); +const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); module.exports = class ProjectTemplateTasksHelper { @@ -74,7 +74,7 @@ module.exports = class ProjectTemplateTasksHelper { } } - let tasksData = await projectTemplateTaskService.taskDocuments( + let tasksData = await projectTemplateTaskQueries.taskDocuments( filterData, ["_id","children","externalId","projectTemplateId","parentId"] ); @@ -91,7 +91,7 @@ module.exports = class ProjectTemplateTasksHelper { } let projectTemplate = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : projectTemplateId },["_id","entityType","externalId"]); @@ -290,7 +290,7 @@ module.exports = class ProjectTemplateTasksHelper { if( !update ) { taskData = - await projectTemplateTaskService.createTemplateTask(allValues); + await projectTemplateTaskQueries.createTemplateTask(allValues); if ( !taskData._id ) { parsedData.STATUS = CONSTANTS.apiResponses.PROJECT_TEMPLATE_TASKS_NOT_CREATED; @@ -302,7 +302,7 @@ module.exports = class ProjectTemplateTasksHelper { } else { taskData = - await projectTemplateTaskService.findOneAndUpdate({ + await projectTemplateTaskQueries.findOneAndUpdate({ _id : parsedData._SYSTEM_ID },{ $set : allValues @@ -316,7 +316,7 @@ module.exports = class ProjectTemplateTasksHelper { if( parsedData.hasAParentTask === "YES" ) { let parentTask = - await projectTemplateTaskService.findOneAndUpdate({ + await projectTemplateTaskQueries.findOneAndUpdate({ externalId : parsedData.parentTaskId },{ $addToSet : { @@ -343,7 +343,7 @@ module.exports = class ProjectTemplateTasksHelper { value : parsedData.parentTaskValue }); - await projectTemplateTaskService.findOneAndUpdate({ + await projectTemplateTaskQueries.findOneAndUpdate({ _id : taskData._id },{ $set : { @@ -358,7 +358,7 @@ module.exports = class ProjectTemplateTasksHelper { } } - await projectTemplateService.updateProjectTemplateDocument + await projectTemplateQueries.updateProjectTemplateDocument ( { _id : template._id }, { $addToSet : { tasks : ObjectId(taskData._id) } } @@ -556,7 +556,7 @@ module.exports = class ProjectTemplateTasksHelper { csvData.data.tasks[currentData._SYSTEM_ID].parentId.toString() !== createdTask._parentTaskId.toString() ) { - await projectTemplateTaskService.findOneAndUpdate( + await projectTemplateTaskQueries.findOneAndUpdate( { _id: csvData.data.tasks[currentData._SYSTEM_ID].parentId }, diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 65e8b413..a591e19e 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -17,9 +17,9 @@ const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/helper"); const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); -const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); -const projectTemplateTaskService = require(DB_SERVICE_BASE_PATH + "/projectTemplateTask"); -const projectService = require(DB_SERVICE_BASE_PATH + "/projects"); +const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); +const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); +const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); module.exports = class ProjectTemplatesHelper { @@ -296,7 +296,7 @@ module.exports = class ProjectTemplatesHelper { let currentData = templates[template]; let templateData = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ status : CONSTANTS.common.PUBLISHED, externalId : currentData.externalId, isReusable : true @@ -317,7 +317,7 @@ module.exports = class ProjectTemplatesHelper { templateData.createdBy = templateData.updatedBy = templateData.userId = userId; templateData.isReusable = true; - let createdTemplate = await projectTemplateService.createTemplate(templateData); + let createdTemplate = await projectTemplateQueries.createTemplate(templateData); if( !createdTemplate._id ) { currentData["_SYSTEM_ID"] = CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; @@ -431,7 +431,7 @@ module.exports = class ProjectTemplatesHelper { } else { const template = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : currentData._SYSTEM_ID, status : CONSTANTS.common.PUBLISHED @@ -451,7 +451,7 @@ module.exports = class ProjectTemplatesHelper { templateData.updatedBy = userId; let projectTemplateUpdated = - await projectTemplateService.findOneAndUpdate({ + await projectTemplateQueries.findOneAndUpdate({ _id : currentData._SYSTEM_ID },{ $set : templateData @@ -544,7 +544,7 @@ module.exports = class ProjectTemplatesHelper { try { let projectTemplateData = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ status : CONSTANTS.common.PUBLISHED, externalId : templateId, isReusable : true @@ -620,7 +620,7 @@ module.exports = class ProjectTemplatesHelper { newProjectTemplate.isReusable = false; let duplicateTemplateDocument = - await projectTemplateService.createTemplate( + await projectTemplateQueries.createTemplate( _.omit(newProjectTemplate, ["_id"]) ); @@ -696,7 +696,7 @@ module.exports = class ProjectTemplatesHelper { } let templateData = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : templateId, isReusable : true @@ -747,7 +747,7 @@ module.exports = class ProjectTemplatesHelper { updateRating.noOfRatings = calculateRating.noOfRatings; ratingUpdated = - await projectTemplateService.findOneAndUpdate({ + await projectTemplateQueries.findOneAndUpdate({ _id : templateId },{ $set : updateRating @@ -809,7 +809,7 @@ module.exports = class ProjectTemplatesHelper { await Promise.all(taskIds.map(async taskId => { - let taskData = await projectTemplateTaskService.taskDocuments( + let taskData = await projectTemplateTaskQueries.taskDocuments( { _id : taskId }); @@ -825,7 +825,7 @@ module.exports = class ProjectTemplatesHelper { newProjectTemplateTask.projectTemplateExternalId = duplicateTemplateExternalId; newProjectTemplateTask.externalId = taskData.externalId +"-"+ UTILS.epochTime(); duplicateTemplateTask = - await projectTemplateTaskService.createTemplateTask( + await projectTemplateTaskQueries.createTemplateTask( _.omit(newProjectTemplateTask, ["_id"]) ); newTaskId.push(duplicateTemplateTask._id); @@ -836,7 +836,7 @@ module.exports = class ProjectTemplatesHelper { if(childTaskIds && childTaskIds.length > 0){ await Promise.all(childTaskIds.map(async childtaskId => { - let childTaskData = await projectTemplateTaskService.taskDocuments( + let childTaskData = await projectTemplateTaskQueries.taskDocuments( { _id : childtaskId }); @@ -852,7 +852,7 @@ module.exports = class ProjectTemplatesHelper { newProjectTemplateChildTask.parentId = duplicateTemplateTask._id; newProjectTemplateChildTask.externalId = childTaskData.externalId +"-"+ UTILS.epochTime(); duplicateChildTemplateTask = - await projectTemplateTaskService.createTemplateTask( + await projectTemplateTaskQueries.createTemplateTask( _.omit(newProjectTemplateChildTask, ["_id"]) ); @@ -861,7 +861,7 @@ module.exports = class ProjectTemplatesHelper { })) if(childTaskIdArray && childTaskIdArray.length > 0){ - let updateTaskData = projectTemplateTaskService.updateTaskDocument( + let updateTaskData = projectTemplateTaskQueries.updateTaskDocument( { _id : duplicateTemplateTask._id }, @@ -880,7 +880,7 @@ module.exports = class ProjectTemplatesHelper { if(newTaskId && newTaskId.length > 0){ - updateDuplicateTemplate = await projectTemplateService.findOneAndUpdate( + updateDuplicateTemplate = await projectTemplateQueries.findOneAndUpdate( { _id : duplicateTemplateId }, @@ -914,7 +914,7 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { - let templateData = await projectTemplateService.templateDocument({ + let templateData = await projectTemplateQueries.templateDocument({ externalId : { $in : externalIds } },["title","metaInformation.goal","externalId"]); @@ -959,7 +959,7 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { - let templateData = await projectTemplateService.templateDocument({ + let templateData = await projectTemplateQueries.templateDocument({ externalId : templateId },"all", [ @@ -999,7 +999,7 @@ module.exports = class ProjectTemplatesHelper { templateData[0].projectId = ""; - let project = await projectService.projectDocument({ + let project = await projectQueries.projectDocument({ userId : userId, projectTemplateId : templateData[0]._id },["_id"]); @@ -1034,7 +1034,7 @@ module.exports = class ProjectTemplatesHelper { try { const templateDocument = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : templateId },["tasks"]); @@ -1050,7 +1050,7 @@ module.exports = class ProjectTemplatesHelper { parentId : { $exists : false } } - tasks = await projectTemplateService.templateDocument(findQuery,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); + tasks = await projectTemplateQueries.templateDocument(findQuery,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); for( let task = 0 ; task < tasks.length ; task ++ ) { @@ -1062,7 +1062,7 @@ module.exports = class ProjectTemplatesHelper { } } - let subTasks = await projectTemplateTaskService.taskDocuments(subTaskQuery, ["projectTemplateId","__v","projectTemplateExternalId"]); + let subTasks = await projectTemplateTaskQueries.taskDocuments(subTaskQuery, ["projectTemplateId","__v","projectTemplateExternalId"]); tasks[task].children = subTasks; } diff --git a/module/reports/helper.js b/module/reports/helper.js index e8ba55f7..fccc2cee 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -9,7 +9,7 @@ const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); const dhitiService = require(GENERICS_FILES_PATH + "/services/dhiti"); -const projectService = require(DB_SERVICE_BASE_PATH + "/projects"); +const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const moment = require('moment'); @@ -65,7 +65,7 @@ module.exports = class ReportsHelper { { "tasks": { $elemMatch: { isDeleted: { $ne: true },syncedAt: { $gte: new Date(startFrom), $lte: new Date(endOf) } } } }, ] - const projectDetails = await projectService.projectDocument( + const projectDetails = await projectQueries.projectDocument( query, ["programId","programInformation.name", "entityInformation.name", "taskReport", "status", "tasks", "categories"], [] @@ -487,7 +487,7 @@ module.exports = class ReportsHelper { query['programId'] = ObjectId(programId); } - const projectDetails = await projectService.projectDocument( + const projectDetails = await projectQueries.projectDocument( query, ["title", "taskReport", diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index a0c4c9fc..71e45e52 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -14,10 +14,10 @@ const projectTemplateTasksHelper = require(MODULES_BASE_PATH + "/project/templat const { v4: uuidv4 } = require('uuid'); const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); const dhitiService = require(GENERICS_FILES_PATH + "/services/dhiti"); -const projectService = require(DB_SERVICE_BASE_PATH + "/projects"); -const projectCategoriesService = require(DB_SERVICE_BASE_PATH + "/projectCategories"); -const projectTemplateService = require(DB_SERVICE_BASE_PATH + "/projectTemplates"); -const projectTemplateTaskService = require(DB_SERVICE_BASE_PATH + "/projectTemplateTask"); +const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); +const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); +const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); +const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); /** * UserProjectsHelper @@ -98,7 +98,7 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - const userProject = await projectService.projectDocument({ + const userProject = await projectQueries.projectDocument({ _id: projectId, userId: userId }, [ @@ -320,7 +320,7 @@ module.exports = class UserProjectsHelper { } let projectUpdated = - await projectService.findOneAndUpdate( + await projectQueries.findOneAndUpdate( { _id: userProject[0]._id }, @@ -467,7 +467,7 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - const projectDetails = await projectService.projectDocument({ + const projectDetails = await projectQueries.projectDocument({ _id: projectId, userId: userId }, "all", @@ -497,7 +497,7 @@ module.exports = class UserProjectsHelper { if (Object.keys(userRoleInformtion).length > 0) { if (!projectDetails[0].userRoleInformtion || !Object.keys(projectDetails[0].userRoleInformtion).length > 0) { - await projectService.findOneAndUpdate({ + await projectQueries.findOneAndUpdate({ _id: projectId },{ $set: {userRoleInformtion: userRoleInformtion} @@ -598,7 +598,7 @@ module.exports = class UserProjectsHelper { ); let result = - await projectService.getAggregate(aggregateData); + await projectQueries.getAggregate(aggregateData); return resolve({ success: true, @@ -670,7 +670,7 @@ module.exports = class UserProjectsHelper { aggregatedData.push(projectData); let projects = - await projectService.getAggregate(aggregatedData); + await projectQueries.getAggregate(aggregatedData); return resolve({ success: true, @@ -774,7 +774,7 @@ module.exports = class UserProjectsHelper { }); const tasksUpdated = - await projectService.findOneAndUpdate({ + await projectQueries.findOneAndUpdate({ _id: projectId, "tasks._id": taskId }, { $set: update }); @@ -801,7 +801,7 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - let project = await projectService.projectDocument( + let project = await projectQueries.projectDocument( { "_id": projectId, "tasks._id": taskId @@ -866,7 +866,7 @@ module.exports = class UserProjectsHelper { currentTask.solutionDetails.programId; } - await projectService.findOneAndUpdate({ + await projectQueries.findOneAndUpdate({ "_id": projectId, "tasks._id": taskId }, { @@ -926,7 +926,7 @@ module.exports = class UserProjectsHelper { if( templateId !== "" ) { let templateDocuments = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ "externalId" : templateId, "isReusable" : false, "solutionId" : { $exists : true } @@ -948,7 +948,7 @@ module.exports = class UserProjectsHelper { if (projectId === "") { - const projectDetails = await projectService.projectDocument({ + const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, userId: userId }, ["_id"]); @@ -1090,7 +1090,7 @@ module.exports = class UserProjectsHelper { projectCreation.data.lastDownloadedAt = new Date(); projectCreation.data.userRoleInformtion = userRoleInformation; - let project = await projectService.createProject(projectCreation.data); + let project = await projectQueries.createProject(projectCreation.data); projectId = project._id; } } @@ -1135,7 +1135,7 @@ module.exports = class UserProjectsHelper { try { const projectTemplateData = - await projectTemplateService.templateDocument({ + await projectTemplateQueries.templateDocument({ status: CONSTANTS.common.PUBLISHED, _id: templateId, isReusable: false @@ -1386,7 +1386,7 @@ module.exports = class UserProjectsHelper { createProject.userRoleInformtion = data.profileInformation; } - let userProject = await projectService.createProject( + let userProject = await projectQueries.createProject( createProject ); @@ -1446,7 +1446,7 @@ module.exports = class UserProjectsHelper { if (!taskIds.length ) { - projectDocument = await projectService.projectDocument + projectDocument = await projectQueries.projectDocument ( query, [ @@ -1478,7 +1478,7 @@ module.exports = class UserProjectsHelper { }} }}] - projectDocument = await projectService.getAggregate(aggregateData); + projectDocument = await projectQueries.getAggregate(aggregateData); } if (!projectDocument.length) { @@ -1692,7 +1692,7 @@ module.exports = class UserProjectsHelper { filterQuery["programId"] = programId; } - let importedProjects = await projectService.projectDocument( + let importedProjects = await projectQueries.projectDocument( filterQuery, [ "solutionInformation", @@ -1933,7 +1933,7 @@ function _projectCategories(categories) { if (categoryIds.length > 0) { categoryData = - await projectCategoriesService.categoryDocuments({ + await projectCategoriesQueries.categoryDocuments({ _id: { $in: categoryIds } }, ["name", "externalId"]); @@ -2059,7 +2059,7 @@ function _assessmentDetails(assessmentData) { if (assessmentData.project) { let templateTasks = - await projectTemplateTaskService.taskDocuments({ + await projectTemplateTaskQueries.taskDocuments({ externalId: assessmentData.project.taskId }, ["_id"]) @@ -2179,7 +2179,7 @@ function _observationDetails(observationData) { if (observationData.project) { let templateTasks = - await projectTemplateTaskService.taskDocuments({ + await projectTemplateTaskQueries.taskDocuments({ externalId: observationData.project.taskId }, ["_id"]) From 4d25aeefff6aea3f16fdf097bbad7cd66cfe62a1 Mon Sep 17 00:00:00 2001 From: Aman Kumar Gupta Date: Wed, 29 Sep 2021 19:42:50 +0530 Subject: [PATCH 011/373] Added:Logs --- app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index cee24dc9..066afc79 100644 --- a/app.js +++ b/app.js @@ -44,11 +44,12 @@ app.use(bodyParser.urlencoded({ limit: "50MB", extended: false })); app.use(express.static("public")); app.all('*', (req, res, next) => { + console.log({"Debugging ML Projects Service": true}); console.log("-------Request log starts here------------------"); console.log("Request URL: ", req.url); - console.log("Request Headers: ", req.headers); - console.log("Request Body: ", req.body); - console.log("Request Files: ", req.files); + console.log("Request Headers: ", JSON.stringify(req.headers)); + console.log("Request Body: ", JSON.stringify(req.body)); + // console.log("Request Files: ", req.files); console.log("-------Request log ends here------------------"); next(); }); From 21b404ed78b0b5f285daa90eb29b44a1888c03e5 Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Thu, 30 Sep 2021 15:40:36 +0530 Subject: [PATCH 012/373] Added url logs in dhiti service --- generics/services/dhiti.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generics/services/dhiti.js b/generics/services/dhiti.js index 62c72af3..4f096aad 100644 --- a/generics/services/dhiti.js +++ b/generics/services/dhiti.js @@ -118,6 +118,8 @@ const projectAndTaskReport = function (token, input, projectPdf) { const url = reportsUrl + CONSTANTS.endpoints.PROJECT_AND_TASK_REPORT + "?projectPdf=" + projectPdf; + + console.log("--- url is- ----",url); let options = { headers : { From afff9ad2a16f922ff2200e7877091a7671d5f37b Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Thu, 30 Sep 2021 19:29:08 +0530 Subject: [PATCH 013/373] Added log in dhiti service --- generics/services/dhiti.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/generics/services/dhiti.js b/generics/services/dhiti.js index 4f096aad..16671a39 100644 --- a/generics/services/dhiti.js +++ b/generics/services/dhiti.js @@ -130,6 +130,8 @@ const projectAndTaskReport = function (token, input, projectPdf) { json : input }; + console.log("--- options is- ----",JSON.stringify(options)); + request.post(url,options,dhitiCallback); function dhitiCallback(err, data) { @@ -139,8 +141,10 @@ const projectAndTaskReport = function (token, input, projectPdf) { }; if (err) { + console.log("--- err is ----",err); result.success = false; } else { + console.log("--- data is ----",data); result["data"] = data.body; } return resolve(result); From 25448afaccdb12cd60d52128c18ee4d39f7f2268 Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Thu, 30 Sep 2021 19:46:51 +0530 Subject: [PATCH 014/373] Added log in dhiti service --- generics/services/dhiti.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/generics/services/dhiti.js b/generics/services/dhiti.js index 16671a39..2e2430ac 100644 --- a/generics/services/dhiti.js +++ b/generics/services/dhiti.js @@ -141,16 +141,17 @@ const projectAndTaskReport = function (token, input, projectPdf) { }; if (err) { - console.log("--- err is ----",err); + console.log("--- err is ----",JSON.stringify(err)); result.success = false; } else { - console.log("--- data is ----",data); + console.log("--- data is ----",JSON.stringify(data.body)); result["data"] = data.body; } return resolve(result); } } catch (error) { + console.log("catch error",error); return reject(error); } }) From 575cf474918f5ac35557f8d9c25d174041e87bfb Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Thu, 30 Sep 2021 20:02:28 +0530 Subject: [PATCH 015/373] Added dhiti changes --- generics/services/dhiti.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/generics/services/dhiti.js b/generics/services/dhiti.js index 2e2430ac..6fdd4659 100644 --- a/generics/services/dhiti.js +++ b/generics/services/dhiti.js @@ -30,7 +30,7 @@ const viewFullReport = function (token,input) { headers : { "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, "content-type": "application/json", - "x-auth-token": token + "x-authenticated-user-token": token }, json : input }; @@ -76,7 +76,7 @@ const entityReport = function (token,input) { headers : { "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, "content-type": "application/json", - "x-auth-token": token + "x-authenticated-user-token": token }, json : input }; @@ -125,13 +125,11 @@ const projectAndTaskReport = function (token, input, projectPdf) { headers : { "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, "content-type": "application/json", - "x-auth-token": token + "x-authenticated-user-token": token }, json : input }; - console.log("--- options is- ----",JSON.stringify(options)); - request.post(url,options,dhitiCallback); function dhitiCallback(err, data) { @@ -141,10 +139,8 @@ const projectAndTaskReport = function (token, input, projectPdf) { }; if (err) { - console.log("--- err is ----",JSON.stringify(err)); result.success = false; } else { - console.log("--- data is ----",JSON.stringify(data.body)); result["data"] = data.body; } return resolve(result); From d6ec2a0f8f550880fe5b0770fef0836e786fec30 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 12 Oct 2021 14:16:08 +0530 Subject: [PATCH 016/373] project link --- controllers/v1/userProjects.js | 231 +++++++++++++++++++++++++++ databaseQueries/projects.js | 1 - generics/constants/common.js | 3 +- generics/services/kendra.js | 9 +- models/projects.js | 6 +- module/library/categories/helper.js | 128 +++++++++++++++ module/project/templates/helper.js | 14 +- module/userProjects/helper.js | 233 ++++++++++++++++++++++++++-- module/userProjects/validator/v1.js | 6 +- 9 files changed, 611 insertions(+), 20 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index bda91e66..c1284026 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -716,4 +716,235 @@ module.exports = class UserProjects extends Abstract { } }) } + + /** + * @api {post} /improvement-project/api/v1/userProjects/list + * Lists of projects. + * @apiVersion 0.0.1 + * @apiName Lists of projects. + * @apiGroup Entity Types + * @apiHeader {String} X-authenticated-user-token Authenticity token + * @apiSampleRequest /improvement-project/api/v1/userProjects/list + * @apiUse successBody + * @apiUse errorBody + * @apiParamExample {json} Request-Body: + * { + "query" : { + "code" : "HM" + }, + "projection" : ["_id","code"] + } + * @apiParamExample {json} Response: + * { + * "message": "Project fetched successfully", + * "status": 200, + * "result" : [ + * { + * "_id": "5d15a959e9185967a6d5e8a6", + * "title": "Come See Our School!- Parent Mela" + }] + } + */ + + /** + * Lists of projects. + * @method + * @name list + * @returns {JSON} List projects. + */ + + async list(req) { + return new Promise(async (resolve, reject) => { + try { + + let projects = await userProjectsHelper.list(req.body); + return resolve(projects); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }); + } + + /** + * @api {post} /improvement-project/api/v1/userProjects/importFromLibrary/:projectTemplateId&isATargetedSolution=false + * Import project from library. + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/importFromLibrary/5f5b32cef16777642d51aaf0 + * @apiParamExample {json} Request: + * { + * "programId" : "", + * "programName" : "My Program", + * "rating" : 2 + * } + * @apiParamExample {json} Response: + * { + "message": "Successfully fetched projects", + "status": 200, + "result": { + "userId": "01c04166-a65e-4e92-a87b-a9e4194e771d", + "isDeleted": false, + "categories": [ + { + "_id": "5f102331665bee6a740714eb", + "externalId": "community", + "name": "Community" + } + ], + "createdBy": "01c04166-a65e-4e92-a87b-a9e4194e771d", + "tasks": [ + { + "_id": "61d6690d-82cb-4db2-8191-8dd945c5e742", + "isDeleted": false, + "isDeletable": false, + "taskSequence": [], + "children": [ + { + "_id": "b5068cef-eefc-4f43-8a29-ab9c2268f451", + "isDeleted": false, + "isDeletable": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "5f72f9998925ec7c60f79a91", + "value": "started" + } + ], + "deleted": false, + "type": "single", + "projectTemplateId": "5f5b32cef16777642d51aaf0", + "name": "Sub task 1", + "externalId": "Sub-task-1", + "description": "Sub-Task-1-Description", + "updatedAt": "2020-09-29T09:08:41.681Z", + "createdAt": "2020-09-29T09:08:41.675Z", + "__v": 0, + "status": "notStarted" + }, + { + "_id": "988ef20f-267f-4bed-9a38-9d7dc6a320e9", + "isDeleted": false, + "isDeletable": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "5f72f9998925ec7c60f79a91", + "value": "started" + } + ], + "deleted": false, + "type": "single", + "projectTemplateId": "5f5b32cef16777642d51aaf0", + "name": "Sub task 2", + "externalId": "Sub-task-2", + "description": "Sub-Task-2-Description", + "updatedAt": "2020-09-29T09:08:41.693Z", + "createdAt": "2020-09-29T09:08:41.689Z", + "__v": 0, + "status": "notStarted" + } + ], + "visibleIf": [], + "deleted": false, + "type": "multiple", + "projectTemplateId": "5f5b32cef16777642d51aaf0", + "name": "Task 1", + "externalId": "task-1", + "description": "Task-1 Description", + "updatedAt": "2020-09-29T09:08:41.691Z", + "createdAt": "2020-09-29T09:08:41.612Z", + "__v": 0, + "status": "notStarted" + }, + { + "_id": "289d9558-b98f-41cf-81d3-92486f114a49", + "isDeleted": false, + "isDeletable": false, + "taskSequence": [], + "children": [], + "visibleIf": [], + "deleted": false, + "type": "single", + "projectTemplateId": "5f5b32cef16777642d51aaf0", + "name": "Task 12", + "externalId": "Task-12", + "description": "Task-1 Description", + "updatedAt": "2020-09-29T09:08:41.667Z", + "createdAt": "2020-09-29T09:08:41.667Z", + "__v": 0, + "status": "notStarted" + } + ], + "updatedBy": "01c04166-a65e-4e92-a87b-a9e4194e771d", + "_id": "5f731d68920a8c3e092e6e4c", + "deleted": false, + "name": "Test-2", + "description": "improving school library", + "status": "notStarted", + "updatedAt": "2020-09-29T11:41:28.656Z", + "createdAt": "2020-09-11T08:18:22.077Z", + "__v": 0, + "solutionInformation": { + "externalId": "01c04166-a65e-4e92-a87b-a9e4194e771d-1601379673400" + }, + "programInformation": { + "externalId": "My Program-1601379673400", + "name": "My Program" + }, + "taskReport": {}, + "entityInformation": {}, + "rationale": "sample", + "primaryAudience": [ + "teachers", + "head master" + ] + }} + * @apiUse successBody + * @apiUse errorBody + */ + + /** + * Import project from library. + * @method + * @name importFromLibrary + * @param {Object} req - request data. + * @param {String} req.params._id - project Template Id. + * @returns {JSON} import project from library. + */ + + async importFromLibrary(req) { + return new Promise(async (resolve, reject) => { + try { + + const createdProject = await userProjectsHelper.importFromLibrary( + req.params._id, + req.body, + req.userDetails.userToken, + req.userDetails.userInformation.userId, + req.query.isATargetedSolution ? req.query.isATargetedSolution : "" + ); + + return resolve({ + message: createdProject.message, + result: createdProject.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } }; \ No newline at end of file diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index a851423b..7c92b5bd 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -52,7 +52,6 @@ module.exports = class Projects { queryObject, projection ).lean(); - return resolve(projects); } catch (error) { diff --git a/generics/constants/common.js b/generics/constants/common.js index 83a4c91c..6b266d45 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -35,6 +35,7 @@ module.exports = { "OBSERVATION_REFERENCE_KEY" : "observation", "ALLOW_MULTIPLE_ASSESSMENTS" : "allowMultipleAssessemts", "IS_RUBRIC_DRIVEN" : "isRubricDriven", - "CRITERIA_LEVEL_REPORT" : "criteriaLevelReport" + "CRITERIA_LEVEL_REPORT" : "criteriaLevelReport", + "LINK" : "link" }; diff --git a/generics/services/kendra.js b/generics/services/kendra.js index 3a0ecfe5..cbe2d0c1 100644 --- a/generics/services/kendra.js +++ b/generics/services/kendra.js @@ -302,11 +302,15 @@ const entityDocuments = function ( * @returns {JSON} - Create user program and solution. */ -const createUserProgramAndSolution = function ( data,userToken ) { +const createUserProgramAndSolution = function ( data,userToken, isATargetedSolution ) { return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + CONSTANTS.endpoints.CREATE_PROGRAM_AND_SOLUTION; + let url = KENDRA_URL + CONSTANTS.endpoints.CREATE_PROGRAM_AND_SOLUTION; + + if( isATargetedSolution == false ) { + url = url + "?isATargetedSolution=" + isATargetedSolution; + } const options = { headers : { @@ -326,6 +330,7 @@ const createUserProgramAndSolution = function ( data,userToken ) { }; if (err) { + console.log(err,"err") result.success = false; } else { diff --git a/models/projects.js b/models/projects.js index b6f60e81..6524e3cd 100644 --- a/models/projects.js +++ b/models/projects.js @@ -112,6 +112,10 @@ module.exports = { type : String, index : true }, - submissions : Object + submissions : Object, + link : { + type : String, + index : true + } } }; diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index 22487a02..f9fc50e9 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -10,6 +10,7 @@ const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); const sessionHelpers = require(GENERIC_HELPERS_PATH+"/sessions"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); +const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const moment = require("moment-timezone"); /** @@ -172,4 +173,131 @@ module.exports = class LibraryCategoriesHelper { }) } + /** + * Details of library projects. + * @method + * @name projectDetails + * @param projectId - project internal id. + * @returns {Object} Details of library projects. + */ + + static projectDetails(projectId,userToken = "", isATargetedSolution = "") { + return new Promise(async (resolve, reject) => { + try { + + let projectsData = await projectTemplateQueries.templateDocument( + { + status : CONSTANTS.common.PUBLISHED, + "_id" : projectId, + "isDeleted" : false, + }, "all", ["__v"]); + + if( !projectsData.length > 0 ) { + throw { + status : HTTP_STATUS_CODE['bad_request'].status, + message : CONSTANTS.apiResponses.PROJECT_NOT_FOUND, + }; + } + + projectsData[0].showProgramAndEntity = false; + + if( projectsData[0].tasks && projectsData[0].tasks.length > 0 ) { + + let tasks = await projectTemplateTaskQueries.taskDocuments( + { + _id : { + $in : projectsData[0].tasks + }, + isDeleted : false + }); + + if( tasks && tasks.length > 0 ) { + + let taskData = {}; + + for ( + let taskPointer = 0; + taskPointer < tasks.length; + taskPointer ++ + ) { + + let currentTask = tasks[taskPointer]; + + if( + currentTask.type === CONSTANTS.common.ASSESSMENT || + currentTask.type === CONSTANTS.common.OBSERVATION + ) { + projectsData[0].showProgramAndEntity = true; + } + + if( currentTask.parentId && currentTask.parentId !== "" ) { + + if( !taskData[currentTask.parentId.toString()] ) { + taskData[currentTask.parentId.toString()].children = []; + } + + taskData[currentTask.parentId.toString()].children.push( + _.omit(currentTask,["parentId"]) + ); + + } else { + currentTask.children = []; + taskData[currentTask._id.toString()] = currentTask; + } + + + } + + projectsData[0].tasks = Object.values(taskData); + + } + } + + if( userToken !== "" ) { + + let userProfileData = await kendraService.getProfile(userToken); + + if( !userProfileData.success ) { + throw { + status : HTTP_STATUS_CODE['bad_request'].status, + message : CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND + } + } + + projectsData[0].userRating = 0; + + if( + userProfileData.data && + userProfileData.data.ratings && + userProfileData.data.ratings.length > 0 + ) { + + let projectIndex = + userProfileData.data.ratings.findIndex( + project => project._id.toString() === projectId.toString() + ); + + if( projectIndex > 0 ) { + projectsData[0].userRating = userProfileData.data.ratings[projectIndex].rating; + } + } + } + + return resolve({ + success: true, + message : CONSTANTS.apiResponses.PROJECTS_FETCHED, + data : projectsData[0] + }); + + } catch (error) { + return resolve({ + status : error.status ? error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data : {} + }); + } + }) + } + }; diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 07a78cb4..8099e776 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -959,9 +959,17 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { - let templateData = await projectTemplateQueries.templateDocument({ - externalId : templateId - },"all", + let findQuery = {}; + + let validateTemplateId = UTILS.isValidMongoId(templateId); + + if( validateTemplateId ) { + findQuery["_id"] = templateId; + } else { + findQuery["externalId"] = templateId; + } + + let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", [ "ratings", "noOfRatings", diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c141c688..225ccf86 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -350,7 +350,8 @@ module.exports = class UserProjectsHelper { programName = "", entities, userToken, - solutionId + solutionId, + isATargetedSolution = "" ) { return new Promise(async (resolve, reject) => { try { @@ -376,7 +377,8 @@ module.exports = class UserProjectsHelper { let solutionAndProgramCreation = await kendraService.createUserProgramAndSolution( programAndSolutionData, - userToken + userToken, + isATargetedSolution ); if (!solutionAndProgramCreation.success) { @@ -409,6 +411,11 @@ module.exports = class UserProjectsHelper { result.programInformation._id = ObjectId(result.programInformation._id); + if( solutionAndProgramCreation.data.parentSolutionInformation ){ + result["link"] = solutionAndProgramCreation.data.parentSolutionInformation.link ? solutionAndProgramCreation.data.parentSolutionInformation.link : ""; + } + + return resolve({ success: true, data: result @@ -478,7 +485,7 @@ module.exports = class UserProjectsHelper { let result = await _projectInformation(projectDetails[0]); if (!result.success) { - return resolve(projectInformation); + return resolve(result); } return resolve({ @@ -890,7 +897,7 @@ module.exports = class UserProjectsHelper { static detailsV2( projectId,solutionId,userId,userToken,bodyData,appName = "",appVersion = "",templateId = "" ) { return new Promise(async (resolve, reject) => { try { - + let solutionExternalId = ""; if( templateId !== "" ) { @@ -901,7 +908,7 @@ module.exports = class UserProjectsHelper { "isReusable" : false, "solutionId" : { $exists : true } },["solutionId","solutionExternalId"]); - + if( !templateDocuments.length > 0 ) { throw { message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, @@ -909,13 +916,11 @@ module.exports = class UserProjectsHelper { } } - solutionId = templateDocuments[0].solutionId; solutionExternalId = templateDocuments[0].solutionExternalId; } let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); - if (projectId === "") { const projectDetails = await projectQueries.projectDocument({ @@ -1070,7 +1075,7 @@ module.exports = class UserProjectsHelper { userId, userRoleInformation ); - + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, @@ -1527,6 +1532,9 @@ module.exports = class UserProjectsHelper { }; } else if( filter == CONSTANTS.common.ASSIGN_TO_ME ) { query["isAPrivateProgram"] = false; + } else{ + query["createdBy"] = userId; + query["referenceFrom"] = CONSTANTS.common.LINK; } } @@ -1544,7 +1552,8 @@ module.exports = class UserProjectsHelper { "projectTemplateId", "solutionExternalId", "lastDownloadedAt", - "hasAcceptedTAndC" + "hasAcceptedTAndC", + "referenceFrom" ] ); @@ -1659,6 +1668,212 @@ module.exports = class UserProjectsHelper { } }) } + + /** + * List of projects. + * @method + * @name list + * @returns {Array} List of projects. + */ + + static list( bodyData ) { + return new Promise(async (resolve, reject) => { + try { + + let projects = await projectQueries.projectDocument( + bodyData.query, + bodyData.projection, + bodyData.skipFields + ); + + return resolve({ + success : true, + message : CONSTANTS.apiResponses.PROJECTS_FETCHED, + result : projects + }); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Sync project. + * @method + * @name importFromLibrary + * @param {String} projectTemplateId - project template id. + * @param {Object} requestedData - body data. + * @param {String} userId - Logged in user id. + * @param {String} userToken - User token. + * @param {Boolean} isATargetedSolution - User targeted or not . + * @returns {Object} Project created information. + */ + + static importFromLibrary(projectTemplateId, requestedData, userToken, userId, isATargetedSolution = "" ) { + return new Promise(async (resolve, reject) => { + try { + + isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); + + let libraryProjects = + await libraryCategoriesHelper.projectDetails( + projectTemplateId, + "", + isATargetedSolution + ); + + if ( + libraryProjects.data && + !Object.keys(libraryProjects.data).length > 0 + ) { + throw { + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + status: HTTP_STATUS_CODE['bad_request'].status + }; + } + + let taskReport = {}; + + if ( + libraryProjects.data.tasks && + libraryProjects.data.tasks.length > 0 + ) { + + libraryProjects.data.tasks = await _projectTask( + libraryProjects.data.tasks, + isATargetedSolution === false ? false : true + ); + + taskReport.total = libraryProjects.data.tasks.length; + + libraryProjects.data.tasks.forEach(task => { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + }); + + libraryProjects.data["taskReport"] = taskReport; + } + + if (requestedData.entityId && requestedData.entityId !== "") { + + let entityInformation = + await _entitiesInformation([requestedData.entityId]); + + if (!entityInformation.success) { + return resolve(entityInformation); + } + + libraryProjects.data["entityInformation"] = entityInformation.data[0]; + libraryProjects.data.entityId = entityInformation.data[0]._id; + } + + if( requestedData.solutionId && requestedData.solutionId !== "" && isATargetedSolution === false){ + + let programAndSolutionInformation = + await this.createProgramAndSolution( + requestedData.programId, + requestedData.programName, + requestedData.entityId ? [requestedData.entityId] : "", + userToken, + requestedData.solutionId, + isATargetedSolution + ); + + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + + libraryProjects.data = _.merge( + libraryProjects.data, + programAndSolutionInformation.data + ) + + libraryProjects.data["referenceFrom"] = CONSTANTS.common.LINK; + } + else if ( + (requestedData.programId && requestedData.programId !== "") || + (requestedData.programName && requestedData.programName !== "" ) + ) { + + let programAndSolutionInformation = + await this.createProgramAndSolution( + requestedData.programId, + requestedData.programName, + requestedData.entityId ? [requestedData.entityId] : "", + userToken + ); + + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + + if ( + libraryProjects.data["entityInformation"] && + libraryProjects.data["entityInformation"].entityType !== + programAndSolutionInformation.data.solutionInformation.entityType + ) { + throw { + message: CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, + status: HTTP_STATUS_CODE['bad_request'].status + } + } + + libraryProjects.data = _.merge( + libraryProjects.data, + programAndSolutionInformation.data + ) + + } + + libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; + libraryProjects.data.lastDownloadedAt = new Date(); + libraryProjects.data.status = CONSTANTS.common.NOT_STARTED_STATUS; + + if (requestedData.startDate) { + libraryProjects.data.startDate = requestedData.startDate; + } + + if (requestedData.endDate) { + libraryProjects.data.endDate = requestedData.endDate; + } + + libraryProjects.data.projectTemplateId = libraryProjects.data._id; + libraryProjects.data.projectTemplateExternalId = libraryProjects.data.externalId; + + let projectCreation = await database.models.projects.create( + _.omit(libraryProjects.data, ["_id"]) + ); + + if (requestedData.rating && requestedData.rating > 0) { + await projectTemplatesHelper.ratings( + projectTemplateId, + requestedData.rating, + userToken + ); + } + + projectCreation = await _projectInformation(projectCreation._doc); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data: projectCreation.data + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + }; /** diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index ecc1593b..b9a193c9 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -13,9 +13,9 @@ module.exports = (req) => { req.checkParams('_id').exists().withMessage("required project id"); req.checkQuery('lastDownloadedAt').exists().withMessage("required last downloaded at"); }, - details : function () { - req.checkParams('_id').exists().withMessage("required project id"); - }, + // details : function () { + // req.checkParams('_id').exists().withMessage("required project id"); + // }, tasksStatus : function () { req.checkParams('_id').exists().withMessage("required project id"); }, From 2c5465dbb7601e5a57dd01ebea770fec4cb541e5 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 12 Oct 2021 22:54:23 +0530 Subject: [PATCH 017/373] PR changes --- generics/services/{kendra.js => core.js} | 33 ++++++++-------- generics/services/{dhiti.js => report.js} | 2 +- .../services/{assessment.js => survey.js} | 3 +- module/library/categories/helper.js | 36 ++--------------- module/project/templateTasks/helper.js | 4 +- module/project/templates/helper.js | 18 ++++----- module/reports/helper.js | 8 ++-- module/solutions/helper.js | 4 +- module/userProjects/helper.js | 39 ++++++++++--------- module/userProjects/validator/v1.js | 3 -- 10 files changed, 59 insertions(+), 91 deletions(-) rename generics/services/{kendra.js => core.js} (94%) rename generics/services/{dhiti.js => report.js} (99%) rename generics/services/{assessment.js => survey.js} (99%) diff --git a/generics/services/kendra.js b/generics/services/core.js similarity index 94% rename from generics/services/kendra.js rename to generics/services/core.js index cbe2d0c1..879c0f52 100644 --- a/generics/services/kendra.js +++ b/generics/services/core.js @@ -9,7 +9,7 @@ const request = require('request'); const fs = require("fs"); -const KENDRA_URL = process.env.ML_CORE_SERVICE_URL; +const ML_CORE_URL = process.env.ML_CORE_SERVICE_URL; /** * Get downloadable file. @@ -21,7 +21,7 @@ const KENDRA_URL = process.env.ML_CORE_SERVICE_URL; const getDownloadableUrl = function (bodyData) { - let fileDownloadUrl = KENDRA_URL + CONSTANTS.endpoints.FILES_DOWNLOADABLE_URL; + let fileDownloadUrl = ML_CORE_URL + CONSTANTS.endpoints.FILES_DOWNLOADABLE_URL; return new Promise((resolve, reject) => { try { @@ -79,7 +79,7 @@ const entityTypesDocuments = function ( return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + CONSTANTS.endpoints.LIST_ENTITY_TYPES; + const url = ML_CORE_URL + CONSTANTS.endpoints.LIST_ENTITY_TYPES; const options = { headers : { @@ -141,7 +141,7 @@ const rolesDocuments = function ( return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + CONSTANTS.endpoints.LIST_USER_ROLES; + const url = ML_CORE_URL + CONSTANTS.endpoints.LIST_USER_ROLES; const options = { headers : { @@ -197,7 +197,7 @@ const formDetails = function ( formName ) { try { const url = - KENDRA_URL + + ML_CORE_URL + CONSTANTS.endpoints.DETAILS_FORM + "/" + formName; const options = { @@ -251,7 +251,7 @@ const entityDocuments = function ( return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + CONSTANTS.endpoints.LIST_ENTITIES; + const url = ML_CORE_URL + CONSTANTS.endpoints.LIST_ENTITIES; const options = { headers : { @@ -302,14 +302,14 @@ const entityDocuments = function ( * @returns {JSON} - Create user program and solution. */ -const createUserProgramAndSolution = function ( data,userToken, isATargetedSolution ) { +const createUserProgramAndSolution = function ( data,userToken, createADuplicateSolution ) { return new Promise(async (resolve, reject) => { try { - let url = KENDRA_URL + CONSTANTS.endpoints.CREATE_PROGRAM_AND_SOLUTION; + let url = ML_CORE_URL + CONSTANTS.endpoints.CREATE_PROGRAM_AND_SOLUTION; if( isATargetedSolution == false ) { - url = url + "?isATargetedSolution=" + isATargetedSolution; + url = url + "?createADuplicateSolution=" + createADuplicateSolution; } const options = { @@ -330,7 +330,6 @@ const createUserProgramAndSolution = function ( data,userToken, isATargetedSolut }; if (err) { - console.log(err,"err") result.success = false; } else { @@ -363,7 +362,7 @@ const getProfile = function ( token ) { return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + CONSTANTS.endpoints.USER_EXTENSION_GET_PROFILE; + const url = ML_CORE_URL + CONSTANTS.endpoints.USER_EXTENSION_GET_PROFILE; const options = { headers : { @@ -416,7 +415,7 @@ const updateUserProfile = function ( token,updateData ) { return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + + const url = ML_CORE_URL + CONSTANTS.endpoints.USER_EXTENSION_UPDATE_USER_PROFILE; const options = { @@ -463,7 +462,7 @@ const userPrivatePrograms = function ( token ) { return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + + const url = ML_CORE_URL + CONSTANTS.endpoints.USER_PRIVATE_PROGRAMS; const options = { @@ -513,7 +512,7 @@ const getUsersByEntityAndRole = function ( return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + CONSTANTS.endpoints.GET_USERS_BY_ENTITY_AND_ROLE + "/" + entityId + "?role=" + role; + const url = ML_CORE_URL + CONSTANTS.endpoints.GET_USERS_BY_ENTITY_AND_ROLE + "/" + entityId + "?role=" + role; const options = { headers : { @@ -565,7 +564,7 @@ const createSolution = function ( bodyData,token ) { return new Promise(async (resolve, reject) => { try { - const url = KENDRA_URL + CONSTANTS.endpoints.CREATE_IMPROVEMENT_PROJECT_SOLUTION; + const url = ML_CORE_URL + CONSTANTS.endpoints.CREATE_IMPROVEMENT_PROJECT_SOLUTION; const options = { headers : { @@ -621,7 +620,7 @@ const solutionBasedOnRoleAndLocation = function ( token,bodyData,typeAndSubType, try { let url = - KENDRA_URL + CONSTANTS.endpoints.SOLUTION_BASED_ON_ROLE_LOCATION+ "?type=" + typeAndSubType + "&subType=" + typeAndSubType; + ML_CORE_URL + CONSTANTS.endpoints.SOLUTION_BASED_ON_ROLE_LOCATION+ "?type=" + typeAndSubType + "&subType=" + typeAndSubType; if( searchText !== "" ) { url = url + "&search=" + searchText; @@ -681,7 +680,7 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution try { const url = - KENDRA_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId; + ML_CORE_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId; const options = { headers : { diff --git a/generics/services/dhiti.js b/generics/services/report.js similarity index 99% rename from generics/services/dhiti.js rename to generics/services/report.js index 6fdd4659..765e9ea7 100644 --- a/generics/services/dhiti.js +++ b/generics/services/report.js @@ -1,5 +1,5 @@ /** - * name : dhiti.js + * name : report.js * author : Rakesh Kumar * Date : 10-Nov-2020 * Description : All dhiti service related information. diff --git a/generics/services/assessment.js b/generics/services/survey.js similarity index 99% rename from generics/services/assessment.js rename to generics/services/survey.js index 09398446..bde6b4f0 100644 --- a/generics/services/assessment.js +++ b/generics/services/survey.js @@ -1,5 +1,5 @@ /** - * name : assessment.js + * name : survey.js * author : Aman Jung Karki * Date : 21-Nov-2020 * Description : Assessment service related information. @@ -565,7 +565,6 @@ const listProgramsBasedOnIds = function ( programIds ) { } else { let response = data.body; - if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index f9fc50e9..dd732aa4 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -6,7 +6,7 @@ */ // Dependencies -const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); +const coreService = require(GENERICS_FILES_PATH + "/services/core"); const sessionHelpers = require(GENERIC_HELPERS_PATH+"/sessions"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); @@ -181,14 +181,14 @@ module.exports = class LibraryCategoriesHelper { * @returns {Object} Details of library projects. */ - static projectDetails(projectId,userToken = "", isATargetedSolution = "") { + static projectDetails(projectId, userToken = "", isATargetedSolution = "") { return new Promise(async (resolve, reject) => { try { let projectsData = await projectTemplateQueries.templateDocument( { - status : CONSTANTS.common.PUBLISHED, "_id" : projectId, + status : CONSTANTS.common.PUBLISHED, "isDeleted" : false, }, "all", ["__v"]); @@ -253,36 +253,6 @@ module.exports = class LibraryCategoriesHelper { } } - if( userToken !== "" ) { - - let userProfileData = await kendraService.getProfile(userToken); - - if( !userProfileData.success ) { - throw { - status : HTTP_STATUS_CODE['bad_request'].status, - message : CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND - } - } - - projectsData[0].userRating = 0; - - if( - userProfileData.data && - userProfileData.data.ratings && - userProfileData.data.ratings.length > 0 - ) { - - let projectIndex = - userProfileData.data.ratings.findIndex( - project => project._id.toString() === projectId.toString() - ); - - if( projectIndex > 0 ) { - projectsData[0].userRating = userProfileData.data.ratings[projectIndex].rating; - } - } - } - return resolve({ success: true, message : CONSTANTS.apiResponses.PROJECTS_FETCHED, diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 17b71fde..c8aa0c00 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -13,7 +13,7 @@ // Dependencies const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/helper"); -const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); +const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); @@ -115,7 +115,7 @@ module.exports = class ProjectTemplateTasksHelper { if ( solutionIds.length > 0 ) { let solutions = - await assessmentService.listSolutions(solutionIds); + await surveyService.listSolutions(solutionIds); if( !solutions.success ) { throw { diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 8099e776..915d18bd 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -13,10 +13,10 @@ // Dependencies const libraryCategoriesHelper = require(MODULES_BASE_PATH + "/library/categories/helper"); -const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); +const coreService = require(GENERICS_FILES_PATH + "/services/core"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/helper"); -const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); +const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); @@ -104,7 +104,7 @@ module.exports = class ProjectTemplatesHelper { if( roleIds.length > 0 ) { let userRolesData = - await kendraService.rolesDocuments({ + await coreService.rolesDocuments({ code : { $in : roleIds } },["code"]); @@ -129,7 +129,7 @@ module.exports = class ProjectTemplatesHelper { if( entityTypes.length > 0 ) { let entityTypesDocument = - await kendraService.entityTypesDocuments(); + await coreService.entityTypesDocuments(); if( !entityTypesDocument.success ) { throw { @@ -560,7 +560,7 @@ module.exports = class ProjectTemplatesHelper { newProjectTemplate.createdBy = newProjectTemplate.updatedBy = userId; let solutionData = - await assessmentService.listSolutions([solutionId]); + await surveyService.listSolutions([solutionId]); if( !solutionData.success ) { throw { @@ -637,7 +637,7 @@ module.exports = class ProjectTemplatesHelper { ); } - await assessmentService.updateSolution( + await surveyService.updateSolution( userToken, { projectTemplateId : duplicateTemplateDocument._id, @@ -686,7 +686,7 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { - let userProfileData = await kendraService.getProfile(userToken); + let userProfileData = await coreService.getProfile(userToken); if( !userProfileData.success ) { throw { @@ -767,7 +767,7 @@ module.exports = class ProjectTemplatesHelper { }); } - await kendraService.updateUserProfile( + await coreService.updateUserProfile( userToken, { "ratings" : improvementProjects @@ -1124,7 +1124,7 @@ function _templateInformation(project) { if( project.programId ) { let programs = - await assessmentService.listProgramsBasedOnIds([project.programId]); + await surveyService.listProgramsBasedOnIds([project.programId]); if( !programs.success ) { throw { diff --git a/module/reports/helper.js b/module/reports/helper.js index fccc2cee..c08c4475 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -8,7 +8,7 @@ // Dependencies const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); -const dhitiService = require(GENERICS_FILES_PATH + "/services/dhiti"); +const reportService = require(GENERICS_FILES_PATH + "/services/report"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const moment = require('moment'); @@ -124,7 +124,7 @@ module.exports = class ReportsHelper { } - let response = await dhitiService.entityReport(userToken, pdfRequest); + let response = await reportService.entityReport(userToken, pdfRequest); if (response && response.success == true) { @@ -270,7 +270,7 @@ module.exports = class ReportsHelper { pdfRequest['entityName'] = projectDetails[0].entityInformation.name; } - let response = await dhitiService.entityReport(userToken, pdfRequest); + let response = await reportService.entityReport(userToken, pdfRequest); if (response && response.success == true) { return resolve({ success: true, @@ -543,7 +543,7 @@ module.exports = class ReportsHelper { "reportType": returnTypeInfo[0].label, "projectDetails": projectData } - let response = await dhitiService.viewFullReport(userToken, data); + let response = await reportService.viewFullReport(userToken, data); if (response && response.success == true) { diff --git a/module/solutions/helper.js b/module/solutions/helper.js index 0b690fe7..87e51da9 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -7,7 +7,7 @@ // Dependencies -const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); +const coreService = require(GENERICS_FILES_PATH + "/services/core"); /** * SolutionsHelper @@ -36,7 +36,7 @@ module.exports = class SolutionsHelper { requestedData.isReusable = false; let solutionCreated = - await kendraService.createSolution(requestedData,token); + await coreService.createSolution(requestedData,token); if( !solutionCreated.success ) { throw { diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 225ccf86..0f54883e 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -7,13 +7,13 @@ // Dependencies -const kendraService = require(GENERICS_FILES_PATH + "/services/kendra"); +const coreService = require(GENERICS_FILES_PATH + "/services/core"); const libraryCategoriesHelper = require(MODULES_BASE_PATH + "/library/categories/helper"); const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); const projectTemplateTasksHelper = require(MODULES_BASE_PATH + "/project/templateTasks/helper"); const { v4: uuidv4 } = require('uuid'); -const assessmentService = require(GENERICS_FILES_PATH + "/services/assessment"); -const dhitiService = require(GENERICS_FILES_PATH + "/services/dhiti"); +const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); +const reportService = require(GENERICS_FILES_PATH + "/services/report"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); @@ -184,7 +184,7 @@ module.exports = class UserProjectsHelper { if (solutionExists) { let updateProgram = - await assessmentService.removeSolutionsFromProgram( + await surveyService.removeSolutionsFromProgram( userToken, userProject[0].programInformation._id, [userProject[0].solutionInformation._id] @@ -375,7 +375,7 @@ module.exports = class UserProjectsHelper { } let solutionAndProgramCreation = - await kendraService.createUserProgramAndSolution( + await coreService.createUserProgramAndSolution( programAndSolutionData, userToken, isATargetedSolution @@ -937,7 +937,7 @@ module.exports = class UserProjectsHelper { if( templateId === "" ) { solutionDetails = - await kendraService.solutionDetailsBasedOnRoleAndLocation( + await coreService.solutionDetailsBasedOnRoleAndLocation( userToken, bodyData, solutionId @@ -954,7 +954,7 @@ module.exports = class UserProjectsHelper { } else { solutionDetails = - await assessmentService.listSolutions([solutionExternalId]); + await surveyService.listSolutions([solutionExternalId]); if( !solutionDetails.success ) { throw { @@ -1043,7 +1043,7 @@ module.exports = class UserProjectsHelper { solutionDetails.entityType && bodyData[solutionDetails.entityType] ) { let entityInformation = - await assessmentService.listEntitiesByLocationIds( + await surveyService.listEntitiesByLocationIds( userToken, [bodyData[solutionDetails.entityType]] ); @@ -1462,7 +1462,7 @@ module.exports = class UserProjectsHelper { delete projectDocument.metaInformation; delete projectDocument.programInformation; - let response = await dhitiService.projectAndTaskReport(userToken, projectDocument, projectPdf); + let response = await reportService.projectAndTaskReport(userToken, projectDocument, projectPdf); if (response && response.success == true) { return resolve({ @@ -1530,6 +1530,9 @@ module.exports = class UserProjectsHelper { query["isAPrivateProgram"] = { $ne : false }; + query["referenceFrom"] = { + $ne : CONSTANTS.common.LINK + }; } else if( filter == CONSTANTS.common.ASSIGN_TO_ME ) { query["isAPrivateProgram"] = false; } else{ @@ -1931,7 +1934,7 @@ function _projectInformation(project) { if (attachments.length > 0) { let attachmentsUrl = - await kendraService.getDownloadableUrl( + await coreService.getDownloadableUrl( { filePaths: attachments } @@ -2154,7 +2157,7 @@ function _entitiesInformation(entityIds) { try { let entityData = - await kendraService.entityDocuments( + await coreService.entityDocuments( entityIds, ["metaInformation", "entityType", "entityTypeId", "registryDetails"] ); @@ -2220,7 +2223,7 @@ function _assessmentDetails(assessmentData) { if (assessmentData.solutionDetails.isReusable) { let createdAssessment = - await assessmentService.createAssessmentSolutionFromTemplate( + await surveyService.createAssessmentSolutionFromTemplate( assessmentData.token, assessmentData.solutionDetails._id, { @@ -2247,7 +2250,7 @@ function _assessmentDetails(assessmentData) { } else { let assignedAssessmentToUser = - await assessmentService.createEntityAssessors( + await surveyService.createEntityAssessors( assessmentData.token, assessmentData.solutionDetails.programId, assessmentData.solutionDetails._id, @@ -2262,7 +2265,7 @@ function _assessmentDetails(assessmentData) { } let entitiesAddedToSolution = - await assessmentService.addEntitiesToSolution( + await surveyService.addEntitiesToSolution( assessmentData.token, assessmentData.solutionDetails._id, [assessmentData.entityId.toString()] @@ -2276,7 +2279,7 @@ function _assessmentDetails(assessmentData) { } let solutionUpdated = - await assessmentService.updateSolution( + await surveyService.updateSolution( assessmentData.token, { "project": assessmentData.project, @@ -2340,7 +2343,7 @@ function _observationDetails(observationData) { if (observationData.solutionDetails.isReusable) { let observationCreatedFromTemplate = - await assessmentService.createObservationFromSolutionTemplate( + await surveyService.createObservationFromSolutionTemplate( observationData.token, observationData.solutionDetails._id, { @@ -2369,7 +2372,7 @@ function _observationDetails(observationData) { } else { let solutionUpdated = - await assessmentService.updateSolution( + await surveyService.updateSolution( observationData.token, { project: observationData.project, @@ -2399,7 +2402,7 @@ function _observationDetails(observationData) { project: observationData.project }; - let observationCreated = await assessmentService.createObservation( + let observationCreated = await surveyService.createObservation( observationData.token, observationData.solutionDetails._id, observation diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index b9a193c9..81c87ce9 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -13,9 +13,6 @@ module.exports = (req) => { req.checkParams('_id').exists().withMessage("required project id"); req.checkQuery('lastDownloadedAt').exists().withMessage("required last downloaded at"); }, - // details : function () { - // req.checkParams('_id').exists().withMessage("required project id"); - // }, tasksStatus : function () { req.checkParams('_id').exists().withMessage("required project id"); }, From 8bad13d889e3301ba37a39e29362a05078797ff2 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 18 Oct 2021 16:40:05 +0530 Subject: [PATCH 018/373] PR change --- generics/services/core.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index 879c0f52..4e8ca33b 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -302,14 +302,14 @@ const entityDocuments = function ( * @returns {JSON} - Create user program and solution. */ -const createUserProgramAndSolution = function ( data,userToken, createADuplicateSolution ) { +const createUserProgramAndSolution = function ( data,userToken, createADuplicateSolution = "" ) { return new Promise(async (resolve, reject) => { try { let url = ML_CORE_URL + CONSTANTS.endpoints.CREATE_PROGRAM_AND_SOLUTION; - if( isATargetedSolution == false ) { - url = url + "?createADuplicateSolution=" + createADuplicateSolution; + if( createADuplicateSolution == false ) { + url = url + "?createADuplicateSolution=" + true; } const options = { From 0e4ad14d272fe498c13b4c45f07e5a5fe7b678c2 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 19 Oct 2021 19:38:01 +0530 Subject: [PATCH 019/373] PR changes --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 0f54883e..bc182f09 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1702,7 +1702,7 @@ module.exports = class UserProjectsHelper { } /** - * Sync project. + * Create project from template. * @method * @name importFromLibrary * @param {String} projectTemplateId - project template id. From 602b5094d55ce0bfe9d9a1f925a5b97fea15b52e Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 20 Oct 2021 12:31:28 +0530 Subject: [PATCH 020/373] auto build --- auto_build_deploy | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 auto_build_deploy diff --git a/auto_build_deploy b/auto_build_deploy new file mode 100644 index 00000000..97b8f690 --- /dev/null +++ b/auto_build_deploy @@ -0,0 +1,55 @@ +@Library('deploy-conf') _ +node('build-slave') { + try { + String ANSI_GREEN = "\u001B[32m" + String ANSI_NORMAL = "\u001B[0m" + String ANSI_BOLD = "\u001B[1m" + String ANSI_RED = "\u001B[31m" + String ANSI_YELLOW = "\u001B[33m" + + ansiColor('xterm') { + timestamps { + stage('Checkout') { + tag_name = env.JOB_NAME.split("/")[-1] + pre_checks() + if (!env.hub_org) { + println(ANSI_BOLD + ANSI_RED + "Uh Oh! Please set a Jenkins environment variable named hub_org with value as registery/sunbidrded" + ANSI_NORMAL) + error 'Please resolve the errors and rerun..' + } else + println(ANSI_BOLD + ANSI_GREEN + "Found environment variable named hub_org with value as: " + hub_org + ANSI_NORMAL) + } + cleanWs() + def scmVars = checkout scm + checkout scm: [$class: 'GitSCM', branches: [[name: "refs/tags/$tag_name"]], userRemoteConfigs: [[url: scmVars.GIT_URL]]] + build_tag = tag_name + "_" + env.BUILD_NUMBER + commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() + artifact_version = tag_name + "_" + commit_hash + echo "build_tag: " + build_tag + + // stage Build + env.NODE_ENV = "build" + print "Environment will be : ${env.NODE_ENV}" + sh('git submodule update --init') + sh('git submodule update --init --recursive --remote') + sh('chmod 777 build.sh') + sh("./build.sh ${build_tag} ${env.NODE_NAME} ${hub_org}") + + + // stage ArchiveArtifacts + archiveArtifacts "metadata.json" + currentBuild.description = "${build_tag}" + + } + } + currentBuild.result = "SUCCESS" + slack_notify(currentBuild.result, tag_name) + email_notify() + auto_build_deploy() + } + catch (err) { + currentBuild.result = "FAILURE" + slack_notify(currentBuild.result, tag_name) + email_notify() + throw err + } +} \ No newline at end of file From e4cd5c4d21d2f8e35d4d05a6e62be461b5264007 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 22 Oct 2021 13:43:51 +0530 Subject: [PATCH 021/373] sync issue fix --- module/userProjects/helper.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index bc182f09..56e9f32b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -26,6 +26,34 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat module.exports = class UserProjectsHelper { + /** + * Projects boolean data. + * @method + * @name booleanData + * @returns {Array} Boolean data. + */ + + static booleanData() { + + const projectsSchema = schemas["projects"].schema; + const projectSchemaKey = Object.keys(projectsSchema); + + let booleanProjects = []; + + projectSchemaKey.forEach(projectSchema => { + const currentSchema = projectsSchema[projectSchema]; + + if ( + currentSchema.hasOwnProperty('default') && + typeof currentSchema.default === "boolean" + ) { + booleanProjects.push(projectSchema); + } + }); + + return booleanProjects; + } + /** * Projects object id field. * @method From 6e6695cca2da8763bc6d82ac4b9380d6ec505a6d Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 25 Oct 2021 12:59:25 +0530 Subject: [PATCH 022/373] logs --- controllers/v1/userProjects.js | 5 ++++- module/library/categories/helper.js | 3 ++- module/userProjects/helper.js | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index c1284026..4014cbc7 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -924,7 +924,7 @@ module.exports = class UserProjects extends Abstract { async importFromLibrary(req) { return new Promise(async (resolve, reject) => { try { - + const createdProject = await userProjectsHelper.importFromLibrary( req.params._id, req.body, @@ -933,12 +933,15 @@ module.exports = class UserProjects extends Abstract { req.query.isATargetedSolution ? req.query.isATargetedSolution : "" ); + console.log(createdProject,"createdProject") return resolve({ + status: createdProject.status, message: createdProject.message, result: createdProject.data }); } catch (error) { + console.log(error,"importFromLibrary error") return reject({ status: error.status || HTTP_STATUS_CODE.internal_server_error.status, message: error.message || HTTP_STATUS_CODE.internal_server_error.message, diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index dd732aa4..deb33d6b 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -192,6 +192,7 @@ module.exports = class LibraryCategoriesHelper { "isDeleted" : false, }, "all", ["__v"]); + console.log(projectsData,"projectsData") if( !projectsData.length > 0 ) { throw { status : HTTP_STATUS_CODE['bad_request'].status, @@ -252,7 +253,7 @@ module.exports = class LibraryCategoriesHelper { } } - + console.log(projectsData[0],"projectsData[0]") return resolve({ success: true, message : CONSTANTS.apiResponses.PROJECTS_FETCHED, diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 56e9f32b..bbc5c1a4 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1746,14 +1746,14 @@ module.exports = class UserProjectsHelper { try { isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); - + console.log(isATargetedSolution,"isATargetedSolution") let libraryProjects = await libraryCategoriesHelper.projectDetails( projectTemplateId, "", isATargetedSolution ); - + console.log(libraryProjects,"libraryProjects") if ( libraryProjects.data && !Object.keys(libraryProjects.data).length > 0 @@ -1896,6 +1896,7 @@ module.exports = class UserProjectsHelper { }); } catch (error) { + console.log(error,"helper error") return resolve({ success: false, message: error.message, From 1e6f2c92b2b13b308a4b9a5611713bd455d29863 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 25 Oct 2021 20:57:42 +0530 Subject: [PATCH 023/373] project already exist check --- controllers/v1/userProjects.js | 2 -- module/userProjects/helper.js | 26 +++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 4014cbc7..7bc1eee2 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -933,7 +933,6 @@ module.exports = class UserProjects extends Abstract { req.query.isATargetedSolution ? req.query.isATargetedSolution : "" ); - console.log(createdProject,"createdProject") return resolve({ status: createdProject.status, message: createdProject.message, @@ -941,7 +940,6 @@ module.exports = class UserProjects extends Abstract { }); } catch (error) { - console.log(error,"importFromLibrary error") return reject({ status: error.status || HTTP_STATUS_CODE.internal_server_error.status, message: error.message || HTTP_STATUS_CODE.internal_server_error.message, diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index bbc5c1a4..9c02affc 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1746,14 +1746,35 @@ module.exports = class UserProjectsHelper { try { isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); - console.log(isATargetedSolution,"isATargetedSolution") + + if( isATargetedSolution === false ) { + + let project = await projectQueries.projectDocument( + { + userId : userId, + createdBy : userId, + projectTemplateId : projectTemplateId + }, "all"); + + if(project && project.length > 0){ + + let projectData = await _projectInformation(project[0]); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data: projectData.data + }); + } + } + let libraryProjects = await libraryCategoriesHelper.projectDetails( projectTemplateId, "", isATargetedSolution ); - console.log(libraryProjects,"libraryProjects") + if ( libraryProjects.data && !Object.keys(libraryProjects.data).length > 0 @@ -1896,7 +1917,6 @@ module.exports = class UserProjectsHelper { }); } catch (error) { - console.log(error,"helper error") return resolve({ success: false, message: error.message, From d66ef45d7be0a44a44c0b1dd28bcdd09b8d27792 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 26 Oct 2021 10:29:41 +0530 Subject: [PATCH 024/373] remove check --- module/userProjects/helper.js | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9c02affc..56e9f32b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1747,27 +1747,6 @@ module.exports = class UserProjectsHelper { isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); - if( isATargetedSolution === false ) { - - let project = await projectQueries.projectDocument( - { - userId : userId, - createdBy : userId, - projectTemplateId : projectTemplateId - }, "all"); - - if(project && project.length > 0){ - - let projectData = await _projectInformation(project[0]); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: projectData.data - }); - } - } - let libraryProjects = await libraryCategoriesHelper.projectDetails( projectTemplateId, From 49dfdefaaac69f14d1322870d995aa296c215658 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 26 Oct 2021 11:58:44 +0530 Subject: [PATCH 025/373] template bulk create issue fix --- module/project/templates/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 915d18bd..dddf692b 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -20,6 +20,7 @@ const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); +const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); module.exports = class ProjectTemplatesHelper { @@ -78,7 +79,7 @@ module.exports = class ProjectTemplatesHelper { if( categoryIds.length > 0 ) { let categories = - await projectCategoriesService.categoryDocuments({ + await projectCategoriesQueries.categoryDocuments({ externalId : { $in : categoryIds } },["externalId","name"]); From 5caa80eb25b931bd4de44d29a467926447a53df9 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 27 Oct 2021 12:35:53 +0530 Subject: [PATCH 026/373] project issue fix --- module/project/templates/helper.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index dddf692b..01613971 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1056,9 +1056,8 @@ module.exports = class ProjectTemplatesHelper { }, parentId : { $exists : false } } - - tasks = await projectTemplateQueries.templateDocument(findQuery,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); + tasks = await projectTemplateTaskQueries.taskDocuments(findQuery,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); for( let task = 0 ; task < tasks.length ; task ++ ) { if( tasks[task].children && tasks[task].children.length > 0 ) { From 526cf4e3eee07f2912e125e0f3c68c899467f7fa Mon Sep 17 00:00:00 2001 From: aman-tunerlabs Date: Wed, 3 Nov 2021 23:05:23 +0530 Subject: [PATCH 027/373] Added console.log and corrected endpoints --- generics/constants/endpoints.js | 3 ++- generics/services/core.js | 4 ++++ module/userProjects/helper.js | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index ace4f25d..4a249318 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -43,5 +43,6 @@ module.exports = { SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION : "/v1/solutions/detailsBasedOnRoleAndLocation", LIST_ENTITIES_BY_LOCATION_IDS : "/v1/entities/listByLocationIds", CREATE_IMPROVEMENT_PROJECT_SOLUTION : "/v1/solutions/create", - PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport" + PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport", + FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl" }; diff --git a/generics/services/core.js b/generics/services/core.js index 4e8ca33b..ec12900e 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -23,6 +23,8 @@ const getDownloadableUrl = function (bodyData) { let fileDownloadUrl = ML_CORE_URL + CONSTANTS.endpoints.FILES_DOWNLOADABLE_URL; + console.log("File Downloadable url is",fileDownloadUrl); + return new Promise((resolve, reject) => { try { @@ -33,9 +35,11 @@ const getDownloadableUrl = function (bodyData) { }; if (err) { + console.log("File download error is",err); result.success = false; } else { let response = data.body; + console.log("File downloaded response is",response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 56e9f32b..f35a87f9 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -516,6 +516,7 @@ module.exports = class UserProjectsHelper { return resolve(result); } + console.log("Project information is",result); return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, @@ -1104,6 +1105,8 @@ module.exports = class UserProjectsHelper { userRoleInformation ); + console.log("Here project final details",projectDetails); + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, @@ -2011,6 +2014,8 @@ function _projectInformation(project) { delete project.solutionInformation; delete project.programInformation; + console.log("project data is",project); + return resolve({ success: true, data: project From 60182bb8dc4211f53cb1ab37f17e29aae7cd2703 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 8 Nov 2021 14:58:28 +0530 Subject: [PATCH 028/373] task issue fix --- module/project/templates/helper.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 01613971..d07d0bba 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1042,8 +1042,8 @@ module.exports = class ProjectTemplatesHelper { const templateDocument = await projectTemplateQueries.templateDocument({ - status : CONSTANTS.common.PUBLISHED, - _id : templateId + _id : templateId, + status : CONSTANTS.common.PUBLISHED },["tasks"]); let tasks = []; @@ -1068,7 +1068,7 @@ module.exports = class ProjectTemplatesHelper { } } - let subTasks = await projectTemplateTaskQueries.taskDocuments(subTaskQuery, ["projectTemplateId","__v","projectTemplateExternalId"]); + let subTasks = await projectTemplateTaskQueries.taskDocuments(subTaskQuery, "all", ["projectTemplateId","__v","projectTemplateExternalId"]); tasks[task].children = subTasks; } From 393f6cd782e4cab7352bbdaf59bd2f9dd49e62f4 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 9 Nov 2021 15:21:38 +0530 Subject: [PATCH 029/373] index added --- models/projects.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/models/projects.js b/models/projects.js index 6524e3cd..07a50412 100644 --- a/models/projects.js +++ b/models/projects.js @@ -37,7 +37,8 @@ module.exports = { syncedAt : Date, isDeleted : { type : Boolean, - default : false + default : false, + index: true }, categories : { type : Array, @@ -45,7 +46,8 @@ module.exports = { }, createdBy : { type : String, - default : "SYSTEM" + default : "SYSTEM", + index: true }, tasks : { type : Array, @@ -101,7 +103,10 @@ module.exports = { type : String, index : true }, - isAPrivateProgram : Boolean, + isAPrivateProgram : { + type : Boolean, + index : true + }, appInformation : Object, userRoleInformtion : Object, hasAcceptedTAndC : { From de35e985c00de1c98d610aef669463531e16da0a Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 9 Nov 2021 19:24:35 +0530 Subject: [PATCH 030/373] PR changes --- models/projects.js | 3 +-- module/userProjects/helper.js | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/models/projects.js b/models/projects.js index 07a50412..305d66ec 100644 --- a/models/projects.js +++ b/models/projects.js @@ -46,8 +46,7 @@ module.exports = { }, createdBy : { type : String, - default : "SYSTEM", - index: true + default : "SYSTEM" }, tasks : { type : Array, diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 56e9f32b..3c24cf3c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -983,7 +983,6 @@ module.exports = class UserProjectsHelper { } else { solutionDetails = await surveyService.listSolutions([solutionExternalId]); - if( !solutionDetails.success ) { throw { message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, @@ -999,7 +998,7 @@ module.exports = class UserProjectsHelper { userId, userToken ); - + if( !projectCreation.success ) { return resolve(projectCreation); } @@ -1179,7 +1178,6 @@ module.exports = class UserProjectsHelper { if (tasksAndSubTasks.length > 0) { result.tasks = _projectTask(tasksAndSubTasks); - result.tasks.forEach(task => { if ( task.type === CONSTANTS.common.ASSESSMENT || @@ -1564,7 +1562,6 @@ module.exports = class UserProjectsHelper { } else if( filter == CONSTANTS.common.ASSIGN_TO_ME ) { query["isAPrivateProgram"] = false; } else{ - query["createdBy"] = userId; query["referenceFrom"] = CONSTANTS.common.LINK; } } From b2d9df253d75af982e60c0776a3af6c444aa121c Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 22 Nov 2021 17:33:06 +0530 Subject: [PATCH 031/373] observation mapped to task --- controllers/v1/userProjects.js | 16 ++++-- generics/constants/api-responses.js | 4 +- generics/constants/common.js | 4 +- generics/kafka/consumers/submissions.js | 10 ++-- module/library/categories/helper.js | 3 +- module/project/templateTasks/helper.js | 52 +++++++++++++++++- module/userProjects/helper.js | 70 +++++++++++++++++-------- 7 files changed, 121 insertions(+), 38 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 7bc1eee2..5cef6e91 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -340,7 +340,8 @@ module.exports = class UserProjects extends Abstract { let taskStatus = await userProjectsHelper.tasksStatus( req.params._id, - req.body.taskIds + req.body.taskIds, + req.userDetails.userToken ); taskStatus.result = taskStatus.data; @@ -358,11 +359,18 @@ module.exports = class UserProjects extends Abstract { } /** - * @api {get} /improvement-project/api/v1/userProjects/solutionDetails/:projectId?taskId=:taskId + * @api {post} /improvement-project/api/v1/userProjects/solutionDetails/:projectId?taskId=:taskId * User project solution details * @apiVersion 1.0.0 * @apiGroup User Projects * @apiSampleRequest /improvement-project/api/v1/userProjects/solutionDetails/5fba54dc5bf46b25a926bee5?taskId=347400e7-8a62-4dad-bc24-af7c5bd70ad1 + * @apiParamExample {json} Request: + { + "role" : "HM", + "state" : "236f5cff-c9af-4366-b0b6-253a1789766a", + "district" : "1dcbc362-ec4c-4559-9081-e0c2864c2931", + "school" : "c5726207-4f9f-4f45-91f1-3e9e8e84d824" + } * @apiParamExample {json} Response: * { "message" : "Solutions details fetched successfully", @@ -409,7 +417,8 @@ module.exports = class UserProjects extends Abstract { let solutionDetails = await userProjectsHelper.solutionDetails( req.userDetails.userToken, req.params._id, - req.query.taskId + req.query.taskId, + req.body ); solutionDetails.result = solutionDetails.data; @@ -948,4 +957,5 @@ module.exports = class UserProjects extends Abstract { } }) } + }; \ No newline at end of file diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 0bc32caf..65810fe0 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -115,5 +115,7 @@ module.exports = { "COULD_NOT_GENERATE_PDF_REPORT": "Could not generate pdf report", "PROJECT_TEMPLATE_DETAILS_FETCHED": "Successfully fetched project template details", "PROJECT_TEMPLATE_EXISTS_IN_SOLUTION" : "Project templates already exists in solution", - "IMPORTED_PROJECTS_FETCHED" : "List of imported projects fetched" + "IMPORTED_PROJECTS_FETCHED" : "List of imported projects fetched", + "NO_OF_SUBMISSION_REQUIRED_MIS_MATCHED" : "noOfSubmissionsRequired should be 1 because allowMultipleAssessemts is false" + }; diff --git a/generics/constants/common.js b/generics/constants/common.js index 6b266d45..ccff6d26 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -36,6 +36,8 @@ module.exports = { "ALLOW_MULTIPLE_ASSESSMENTS" : "allowMultipleAssessemts", "IS_RUBRIC_DRIVEN" : "isRubricDriven", "CRITERIA_LEVEL_REPORT" : "criteriaLevelReport", - "LINK" : "link" + "LINK" : "link", + "DEFAULT_SUBMISSION_REQUIRED" : 1, + "STARTED" : "started", }; diff --git a/generics/kafka/consumers/submissions.js b/generics/kafka/consumers/submissions.js index 92bc5121..9c56c4d3 100644 --- a/generics/kafka/consumers/submissions.js +++ b/generics/kafka/consumers/submissions.js @@ -27,14 +27,12 @@ var messageReceived = function (message) { let parsedMessage = JSON.parse(message.value); let submissionDocument = { - "submissionDetails._id" : parsedMessage._id.toString(), - "submissionDetails.status" : parsedMessage.status, - "submissionDetails.completedDate" : - parsedMessage.submissionDate ? parsedMessage.submissionDate : "" + "_id" : parsedMessage._id.toString(), + "status" : parsedMessage.status, + "completedDate" : parsedMessage.submissionDate ? parsedMessage.submissionDate : "" }; - - await userProjectsHelper.updateTask( + await userProjectsHelper.pushSubmissionToTask( parsedMessage.projectId, parsedMessage.taskId, submissionDocument diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index deb33d6b..dd732aa4 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -192,7 +192,6 @@ module.exports = class LibraryCategoriesHelper { "isDeleted" : false, }, "all", ["__v"]); - console.log(projectsData,"projectsData") if( !projectsData.length > 0 ) { throw { status : HTTP_STATUS_CODE['bad_request'].status, @@ -253,7 +252,7 @@ module.exports = class LibraryCategoriesHelper { } } - console.log(projectsData[0],"projectsData[0]") + return resolve({ success: true, message : CONSTANTS.apiResponses.PROJECTS_FETCHED, diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index c8aa0c00..9b05fbab 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -198,7 +198,6 @@ module.exports = class ProjectTemplateTasksHelper { } else if ( solutionTypes.includes(allValues.type) ) { allValues.solutionDetails = {}; - if( parsedData.solutionType && parsedData.solutionType !== "" ) { allValues.solutionDetails.type = parsedData.solutionType; } else { @@ -244,11 +243,31 @@ module.exports = class ProjectTemplateTasksHelper { CONSTANTS.apiResponses.MIS_MATCHED_PROJECT_AND_TASK_ENTITY_TYPE; } else { + let projectionFields = _solutionDocumentProjectionFieldsForTask(); + allValues.solutionDetails.noOfSubmissionsRequired = CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; + + if ( parsedData.noOfSubmissionsRequired && parsedData.noOfSubmissionsRequired != "" ) { + + // noOfSubmissionsRequired present in csv + if ( parsedData.noOfSubmissionsRequired > CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED ) { + if ( solutionData[parsedData.solutionId].allowMultipleAssessemts ) { + allValues.solutionDetails.noOfSubmissionsRequired = parsedData.noOfSubmissionsRequired; + } + } + + }else{ + // noOfSubmissionsRequired not present in csv + if ( solutionData[parsedData.solutionId].noOfSubmissionsRequired ) { + projectionFields.push("noOfSubmissionsRequired"); + } + } + allValues.solutionDetails = _.pick( solutionData[parsedData.solutionId], - ["_id","isReusable","externalId","name","programId","type","subType","allowMultipleAssessemts","isRubricDriven","criteriaLevelReport","scoringSystem"] + projectionFields ); + } } @@ -577,4 +596,33 @@ module.exports = class ProjectTemplateTasksHelper { } }) } + }; + +/** + * Helper function for list of solution fields to be sent in response. + * @method + * @name solutionDocumentProjectionFieldsForTask + * @returns {Promise} Returns a Promise. + */ + +function _solutionDocumentProjectionFieldsForTask() { + + let projectionFields = [ + "_id", + "isReusable", + "externalId", + "name", + "programId", + "type", + "subType", + "allowMultipleAssessemts", + "isRubricDriven", + "criteriaLevelReport", + "scoringSystem" + ]; + + return projectionFields; +} + + diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 3c24cf3c..de539331 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -262,9 +262,10 @@ module.exports = class UserProjectsHelper { ); } else { - if (userProject[0].tasks[taskIndex].submissionDetails) { - task.submissionDetails = userProject[0].tasks[taskIndex].submissionDetails; + if (userProject[0].tasks[taskIndex].submissions) { + task.submissions = userProject[0].tasks[taskIndex].submissions; } + userProject[0].tasks[taskIndex] = task; } }); @@ -700,7 +701,7 @@ module.exports = class UserProjectsHelper { * @returns {Object} */ - static tasksStatus(projectId, taskIds = []) { + static tasksStatus(projectId, taskIds = [], userToken ) { return new Promise(async (resolve, reject) => { try { @@ -727,13 +728,34 @@ module.exports = class UserProjectsHelper { _id: currentTask._id }; + let completedSubmissionCount = 0; + + let noOfSubmissionsRequired = (currentTask.solutionDetails && currentTask.solutionDetails.noOfSubmissionsRequired ) ? currentTask.solutionDetails.noOfSubmissionsRequired : CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; + if ( currentTask.type === CONSTANTS.common.ASSESSMENT || currentTask.type === CONSTANTS.common.OBSERVATION ) { - data["submissionDetails"] = - currentTask.submissionDetails ? currentTask.submissionDetails : {}; + data["submissionStatus"] = CONSTANTS.common.STARTED; + + let submissionDetails = currentTask.observationInformation ? currentTask.observationInformation : {}; + + if( currentTask.submissions && currentTask.submissions.length > 0 ) { + Object.assign(submissionDetails, currentTask.submissions[0]); + completedSubmissionCount = currentTask.submissions.filter((eachSubmission) => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS).length; + } + + data["submissionDetails"] = submissionDetails; + + if ( completedSubmissionCount >= noOfSubmissionsRequired ) { + data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; + } + + if ( currentTask.type === CONSTANTS.common.OBSERVATION ) { + data["submissions"] = currentTask.submissions ? currentTask.submissions : []; + } + } result.push(data); @@ -768,21 +790,19 @@ module.exports = class UserProjectsHelper { * @returns {Object} */ - static updateTask(projectId, taskId, updatedData) { + static pushSubmissionToTask(projectId, taskId, updatedData) { return new Promise(async (resolve, reject) => { try { let update = {}; - Object.keys(updatedData).forEach(taskData => { - update["tasks.$." + taskData] = updatedData[taskData]; - }); + update["tasks.$." + "submissions"] = updatedData const tasksUpdated = await projectQueries.findOneAndUpdate({ _id: projectId, "tasks._id": taskId - }, { $set: update }); + }, { $push: update }); return resolve(tasksUpdated); @@ -802,7 +822,7 @@ module.exports = class UserProjectsHelper { * @returns {Object} */ - static solutionDetails(userToken, projectId, taskId) { + static solutionDetails(userToken, projectId, taskId, bodyData = {}) { return new Promise(async (resolve, reject) => { try { @@ -816,7 +836,8 @@ module.exports = class UserProjectsHelper { "tasks.type", "tasks._id", "tasks.solutionDetails", - "tasks.submissionDetails", + "tasks.submissions", + "tasks.observationInformation", "tasks.externalId", "programInformation._id", "projectTemplateId" @@ -839,8 +860,8 @@ module.exports = class UserProjectsHelper { programId: project[0].programInformation._id } - if (currentTask.submissionDetails) { - assessmentOrObservationData = currentTask.submissionDetails; + if (currentTask.observationInformation) { + assessmentOrObservationData = currentTask.observationInformation; } else { let assessmentOrObservation = { @@ -852,12 +873,13 @@ module.exports = class UserProjectsHelper { "_id": projectId, "taskId": taskId } + }; let assignedAssessmentOrObservation = solutionDetails.type === CONSTANTS.common.ASSESSMENT ? await _assessmentDetails(assessmentOrObservation) : - await _observationDetails(assessmentOrObservation); + await _observationDetails(assessmentOrObservation, bodyData); if (!assignedAssessmentOrObservation.success) { return resolve(assignedAssessmentOrObservation); @@ -876,7 +898,7 @@ module.exports = class UserProjectsHelper { "tasks._id": taskId }, { $set: { - "tasks.$.submissionDetails": assessmentOrObservationData + "tasks.$.observationInformation": assessmentOrObservationData } }); @@ -989,6 +1011,7 @@ module.exports = class UserProjectsHelper { status : HTTP_STATUS_CODE['bad_request'].status } } + solutionDetails = solutionDetails.data[0]; } @@ -2347,7 +2370,7 @@ function _assessmentDetails(assessmentData) { * @returns {Object} */ -function _observationDetails(observationData) { +function _observationDetails(observationData, bodyData = {}) { return new Promise(async (resolve, reject) => { try { @@ -2427,21 +2450,22 @@ function _observationDetails(observationData) { project: observationData.project }; + if ( bodyData && Object.keys(bodyData).length > 0 ) { + Object.assign(observation, bodyData); + } + let observationCreated = await surveyService.createObservation( observationData.token, observationData.solutionDetails._id, observation ); - if (!observationCreated.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.OBSERVATION_NOT_CREATED - } + if ( observationCreated.success ) { + result["observationId"] = observationCreated.data._id; } result["solutionId"] = observationData.solutionDetails._id; - result["observationId"] = observationCreated.data._id; + } return resolve({ From 918f5d186a50fa2c44413eeed8ae8d8f978ef70a Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 23 Nov 2021 09:24:45 +0530 Subject: [PATCH 032/373] PR changes --- controllers/v1/userProjects.js | 3 +-- generics/constants/api-responses.js | 2 +- module/userProjects/helper.js | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 5cef6e91..a5da5a5f 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -340,8 +340,7 @@ module.exports = class UserProjects extends Abstract { let taskStatus = await userProjectsHelper.tasksStatus( req.params._id, - req.body.taskIds, - req.userDetails.userToken + req.body.taskIds ); taskStatus.result = taskStatus.data; diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 65810fe0..b12790e6 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -116,6 +116,6 @@ module.exports = { "PROJECT_TEMPLATE_DETAILS_FETCHED": "Successfully fetched project template details", "PROJECT_TEMPLATE_EXISTS_IN_SOLUTION" : "Project templates already exists in solution", "IMPORTED_PROJECTS_FETCHED" : "List of imported projects fetched", - "NO_OF_SUBMISSION_REQUIRED_MIS_MATCHED" : "noOfSubmissionsRequired should be 1 because allowMultipleAssessemts is false" + "MIN_NO_OF_SUBMISSION_REQUIRED_MIS_MATCHED" : "minNoOfSubmissionsRequired should be 1 because allowMultipleAssessemts is false" }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index de539331..8a1cf339 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -701,7 +701,7 @@ module.exports = class UserProjectsHelper { * @returns {Object} */ - static tasksStatus(projectId, taskIds = [], userToken ) { + static tasksStatus(projectId, taskIds = []) { return new Promise(async (resolve, reject) => { try { @@ -730,7 +730,7 @@ module.exports = class UserProjectsHelper { let completedSubmissionCount = 0; - let noOfSubmissionsRequired = (currentTask.solutionDetails && currentTask.solutionDetails.noOfSubmissionsRequired ) ? currentTask.solutionDetails.noOfSubmissionsRequired : CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; + let minNoOfSubmissionsRequired = currentTask.solutionDetails.minNoOfSubmissionsRequired; if ( currentTask.type === CONSTANTS.common.ASSESSMENT || @@ -748,7 +748,7 @@ module.exports = class UserProjectsHelper { data["submissionDetails"] = submissionDetails; - if ( completedSubmissionCount >= noOfSubmissionsRequired ) { + if (completedSubmissionCount >= minNoOfSubmissionsRequired ) { data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; } From d0dc347fbbad185d9852d9090e8cae4d37194f13 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 23 Nov 2021 15:31:57 +0530 Subject: [PATCH 033/373] PR changes --- module/project/templateTasks/helper.js | 16 ++++++++-------- module/userProjects/helper.js | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 9b05fbab..fbd56553 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -244,21 +244,21 @@ module.exports = class ProjectTemplateTasksHelper { } else { let projectionFields = _solutionDocumentProjectionFieldsForTask(); - allValues.solutionDetails.noOfSubmissionsRequired = CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; + allValues.solutionDetails.minNoOfSubmissionsRequired = CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; - if ( parsedData.noOfSubmissionsRequired && parsedData.noOfSubmissionsRequired != "" ) { + if (parsedData.minNoOfSubmissionsRequired && parsedData.minNoOfSubmissionsRequired != "" ) { - // noOfSubmissionsRequired present in csv - if ( parsedData.noOfSubmissionsRequired > CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED ) { + // minNoOfSubmissionsRequired present in csv + if (parsedData.minNoOfSubmissionsRequired > CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED ) { if ( solutionData[parsedData.solutionId].allowMultipleAssessemts ) { - allValues.solutionDetails.noOfSubmissionsRequired = parsedData.noOfSubmissionsRequired; + allValues.solutionDetails.minNoOfSubmissionsRequired = parsedData.minNoOfSubmissionsRequired; } } }else{ - // noOfSubmissionsRequired not present in csv - if ( solutionData[parsedData.solutionId].noOfSubmissionsRequired ) { - projectionFields.push("noOfSubmissionsRequired"); + // minNoOfSubmissionsRequired not present in csv + if (solutionData[parsedData.solutionId].minNoOfSubmissionsRequired ) { + projectionFields.push("minNoOfSubmissionsRequired"); } } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 8a1cf339..1b7779e4 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -743,7 +743,7 @@ module.exports = class UserProjectsHelper { if( currentTask.submissions && currentTask.submissions.length > 0 ) { Object.assign(submissionDetails, currentTask.submissions[0]); - completedSubmissionCount = currentTask.submissions.filter((eachSubmission) => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS).length; + completedSubmissionCount = currentTask.submissions.length; } data["submissionDetails"] = submissionDetails; From 9294683cd3de9c992d5b38fe1f49119803239d56 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 24 Nov 2021 10:44:16 +0530 Subject: [PATCH 034/373] changes for survey api --- generics/services/survey.js | 14 +++++++++----- module/userProjects/helper.js | 9 +++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/generics/services/survey.js b/generics/services/survey.js index bde6b4f0..76a6f43f 100644 --- a/generics/services/survey.js +++ b/generics/services/survey.js @@ -374,7 +374,7 @@ const listSolutions = function (solutionIds) { const options = { headers : { "content-type": "application/json", - "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, + "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN }, json : { solutionIds : solutionIds @@ -388,12 +388,11 @@ const listSolutions = function (solutionIds) { let result = { success : true }; - + if (err) { result.success = false; } else { let response = data.body; - if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { @@ -479,7 +478,7 @@ const updateSolution = function ( token,updateData,solutionExternalId ) { * @returns {JSON} - Create observation. */ -const createObservation = function (token,solutionId,data) { +const createObservation = function (token,solutionId,data, userRoleAndProfileInformation = {}) { return new Promise(async (resolve, reject) => { try { @@ -487,7 +486,7 @@ const createObservation = function (token,solutionId,data) { ASSESSMENT_URL + CONSTANTS.endpoints.CREATE_OBSERVATIONS + "?solutionId=" + solutionId; - const options = { + let options = { headers : { "content-type": "application/json", "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, @@ -497,6 +496,10 @@ const createObservation = function (token,solutionId,data) { data : data } }; + + if ( userRoleAndProfileInformation && Object.keys(userRoleAndProfileInformation).length > 0){ + options.json.userRoleAndProfileInformation = userRoleAndProfileInformation; + } request.post(createdObservationUrl,options,assessmentCallback); @@ -518,6 +521,7 @@ const createObservation = function (token,solutionId,data) { } } + return resolve(result); } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1b7779e4..f9d5ec83 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2370,7 +2370,7 @@ function _assessmentDetails(assessmentData) { * @returns {Object} */ -function _observationDetails(observationData, bodyData = {}) { +function _observationDetails(observationData, userRoleAndProfileInformation = {}) { return new Promise(async (resolve, reject) => { try { @@ -2450,14 +2450,11 @@ function _observationDetails(observationData, bodyData = {}) { project: observationData.project }; - if ( bodyData && Object.keys(bodyData).length > 0 ) { - Object.assign(observation, bodyData); - } - let observationCreated = await surveyService.createObservation( observationData.token, observationData.solutionDetails._id, - observation + observation, + userRoleAndProfileInformation && Object.keys(userRoleAndProfileInformation).length > 0 ? userRoleAndProfileInformation : {} ); if ( observationCreated.success ) { From 30b4f3fedc30cdfb34f679c263ffa6b79616a72c Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 24 Nov 2021 11:51:24 +0530 Subject: [PATCH 035/373] fix task status api --- module/userProjects/helper.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index f9d5ec83..de52c9ce 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -728,15 +728,15 @@ module.exports = class UserProjectsHelper { _id: currentTask._id }; - let completedSubmissionCount = 0; - - let minNoOfSubmissionsRequired = currentTask.solutionDetails.minNoOfSubmissionsRequired; - if ( currentTask.type === CONSTANTS.common.ASSESSMENT || currentTask.type === CONSTANTS.common.OBSERVATION ) { + let completedSubmissionCount = 0; + + let minNoOfSubmissionsRequired = currentTask.solutionDetails.minNoOfSubmissionsRequired; + data["submissionStatus"] = CONSTANTS.common.STARTED; let submissionDetails = currentTask.observationInformation ? currentTask.observationInformation : {}; From 5eb3880920df5984aba16c9574368d0c2ae0e37e Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 24 Nov 2021 17:59:54 +0530 Subject: [PATCH 036/373] task upload fix --- module/project/templateTasks/helper.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index fbd56553..6fc124e3 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -244,14 +244,14 @@ module.exports = class ProjectTemplateTasksHelper { } else { let projectionFields = _solutionDocumentProjectionFieldsForTask(); - allValues.solutionDetails.minNoOfSubmissionsRequired = CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; + allValues.solutionDetails["minNoOfSubmissionsRequired"] = CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; if (parsedData.minNoOfSubmissionsRequired && parsedData.minNoOfSubmissionsRequired != "" ) { // minNoOfSubmissionsRequired present in csv - if (parsedData.minNoOfSubmissionsRequired > CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED ) { + if ( parsedData.minNoOfSubmissionsRequired > CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED ) { if ( solutionData[parsedData.solutionId].allowMultipleAssessemts ) { - allValues.solutionDetails.minNoOfSubmissionsRequired = parsedData.minNoOfSubmissionsRequired; + allValues.solutionDetails["minNoOfSubmissionsRequired"] = parsedData.minNoOfSubmissionsRequired; } } @@ -262,11 +262,10 @@ module.exports = class ProjectTemplateTasksHelper { } } - allValues.solutionDetails = - _.pick( + Object.assign(allValues.solutionDetails, _.pick( solutionData[parsedData.solutionId], projectionFields - ); + )) } From d5cf04bac948f06bad7659d1218a1d0d8189f84c Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 25 Nov 2021 12:40:59 +0530 Subject: [PATCH 037/373] task status api changes --- module/userProjects/helper.js | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index de52c9ce..65f62e99 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -735,25 +735,33 @@ module.exports = class UserProjectsHelper { let completedSubmissionCount = 0; - let minNoOfSubmissionsRequired = currentTask.solutionDetails.minNoOfSubmissionsRequired; + let minNoOfSubmissionsRequired = currentTask.solutionDetails.minNoOfSubmissionsRequired ? currentTask.solutionDetails.minNoOfSubmissionsRequired : CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; data["submissionStatus"] = CONSTANTS.common.STARTED; let submissionDetails = currentTask.observationInformation ? currentTask.observationInformation : {}; - - if( currentTask.submissions && currentTask.submissions.length > 0 ) { - Object.assign(submissionDetails, currentTask.submissions[0]); - completedSubmissionCount = currentTask.submissions.length; - } - data["submissionDetails"] = submissionDetails; + + if ( currentTask.submissions && currentTask.submissions.length > 0 ) { - if (completedSubmissionCount >= minNoOfSubmissionsRequired ) { - data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; - } + let completedSubmissionDoc; + completedSubmissionCount = currentTask.submissions.filter((eachSubmission) => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS).length; + + if (completedSubmissionCount >= minNoOfSubmissionsRequired ) { + + completedSubmissionDoc = currentTask.submissions.find(eachSubmission => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS); + data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; + + } else { + + completedSubmissionDoc = currentTask.submissions.find(eachSubmission => eachSubmission.status === CONSTANTS.common.STARTED); + } + + Object.assign(data["submissionDetails"],completedSubmissionDoc) + + } else { - if ( currentTask.type === CONSTANTS.common.OBSERVATION ) { - data["submissions"] = currentTask.submissions ? currentTask.submissions : []; + data["submissionDetails"].status = CONSTANTS.common.STARTED; } } From 3d603d6bc0d4f0dba1725c47853950fec383e443 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Fri, 26 Nov 2021 18:51:29 +0530 Subject: [PATCH 038/373] Give only solution details if entity information is not present. --- module/userProjects/helper.js | 88 +++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 65f62e99..a2ef8625 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -863,57 +863,63 @@ module.exports = class UserProjectsHelper { let solutionDetails = currentTask.solutionDetails; - let assessmentOrObservationData = { - entityId: project[0].entityInformation._id, - programId: project[0].programInformation._id - } + let assessmentOrObservationData = {}; + + if (project[0].entityInformation && project[0].entityInformation._id && project[0].programInformation && project[0].programInformation._id) { + + assessmentOrObservationData = { + entityId: project[0].entityInformation._id, + programId: project[0].programInformation._id + } - if (currentTask.observationInformation) { - assessmentOrObservationData = currentTask.observationInformation; - } else { - - let assessmentOrObservation = { - token: userToken, - solutionDetails: solutionDetails, - entityId: assessmentOrObservationData.entityId, - programId: assessmentOrObservationData.programId, - project: { - "_id": projectId, - "taskId": taskId - } + if (currentTask.observationInformation) { + assessmentOrObservationData = currentTask.observationInformation; + } else { + + let assessmentOrObservation = { + token: userToken, + solutionDetails: solutionDetails, + entityId: assessmentOrObservationData.entityId, + programId: assessmentOrObservationData.programId, + project: { + "_id": projectId, + "taskId": taskId + } - }; + }; - let assignedAssessmentOrObservation = - solutionDetails.type === CONSTANTS.common.ASSESSMENT ? - await _assessmentDetails(assessmentOrObservation) : - await _observationDetails(assessmentOrObservation, bodyData); + let assignedAssessmentOrObservation = + solutionDetails.type === CONSTANTS.common.ASSESSMENT ? + await _assessmentDetails(assessmentOrObservation) : + await _observationDetails(assessmentOrObservation, bodyData); - if (!assignedAssessmentOrObservation.success) { - return resolve(assignedAssessmentOrObservation); - } + if (!assignedAssessmentOrObservation.success) { + return resolve(assignedAssessmentOrObservation); + } - assessmentOrObservationData = - _.merge(assessmentOrObservationData, assignedAssessmentOrObservation.data); + assessmentOrObservationData = + _.merge(assessmentOrObservationData, assignedAssessmentOrObservation.data); - if (!currentTask.solutionDetails.isReusable) { - assessmentOrObservationData["programId"] = - currentTask.solutionDetails.programId; - } - - await projectQueries.findOneAndUpdate({ - "_id": projectId, - "tasks._id": taskId - }, { - $set: { - "tasks.$.observationInformation": assessmentOrObservationData + if (!currentTask.solutionDetails.isReusable) { + assessmentOrObservationData["programId"] = + currentTask.solutionDetails.programId; } - }); - } + await projectQueries.findOneAndUpdate({ + "_id": projectId, + "tasks._id": taskId + }, { + $set: { + "tasks.$.observationInformation": assessmentOrObservationData + } + }); - assessmentOrObservationData["entityType"] = project[0].entityInformation.entityType; + } + assessmentOrObservationData["entityType"] = project[0].entityInformation.entityType; + + } + if(currentTask.solutionDetails && !(_.isEmpty(currentTask.solutionDetails))) { assessmentOrObservationData.solutionDetails = currentTask.solutionDetails; From 1905279a18a347f68ffb0e26b4e289f24d7e675b Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 6 Dec 2021 14:19:49 +0530 Subject: [PATCH 039/373] isReusable issue fix --- module/project/templates/helper.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index d07d0bba..7ea53466 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -436,7 +436,7 @@ module.exports = class ProjectTemplatesHelper { status : CONSTANTS.common.PUBLISHED, _id : currentData._SYSTEM_ID, status : CONSTANTS.common.PUBLISHED - },["_id","categories"]); + },["_id","categories", "isReusable"]); if ( !(template.length > 0 && template[0]._id) ) { currentData["UPDATE_STATUS"] = @@ -449,6 +449,10 @@ module.exports = class ProjectTemplatesHelper { userId ); + if(template[0].isReusable === false) { + templateData.isReusable = false; + } + templateData.updatedBy = userId; let projectTemplateUpdated = From 3925481590730db0904a8956c321177484d64205 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 9 Dec 2021 23:19:00 +0530 Subject: [PATCH 040/373] mutiple subrole story --- controllers/v1/reports.js | 8 ++++++-- controllers/v1/userProjects.js | 6 +++--- module/reports/helper.js | 3 +-- module/userProjects/helper.js | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/controllers/v1/reports.js b/controllers/v1/reports.js index 4d9e09fc..71f5f5fc 100644 --- a/controllers/v1/reports.js +++ b/controllers/v1/reports.js @@ -96,11 +96,15 @@ module.exports = class Reports { } /** - * @api {get} /improvement-project/api/v1/reports/getProgramsByEntity/:_id + * @api {post} /improvement-project/api/v1/reports/getProgramsByEntity/:_id * Get programs by entity. * @apiVersion 1.0.0 * @apiGroup Reports - * @apiSampleRequest /improvement-project/api/v1/reports/getProgramsByEntity/5ddf79ff47e9260268c9547a?page=1&limi1=10&search=a + * @apiSampleRequest /improvement-project/api/v1/reports/getProgramsByEntity/5ddf79ff47e9260268c9547a?page=1&limit=10&search=a + * @apiParamExample {json} Request: + { + "role": "HM,DEO", + } * @apiParamExample {json} Response: * { "message": "Programs fetched successfully", diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index a5da5a5f..1c2bbf23 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -163,7 +163,7 @@ module.exports = class UserProjects extends Abstract { * @apiSampleRequest /improvement-project/api/v1/userProjects/details/5f731631e8d7cd3b88ac0659?programId=5f4e538bdf6dd17bab708173&solutionId=5f8688e7d7f86f040b77f460&templateId=IDEAIMP4 * @apiParamExample {json} Request: { - "role" : "HM", + "role" : "HM,DEO", "state" : "236f5cff-c9af-4366-b0b6-253a1789766a", "district" : "1dcbc362-ec4c-4559-9081-e0c2864c2931", "school" : "c5726207-4f9f-4f45-91f1-3e9e8e84d824" @@ -365,7 +365,7 @@ module.exports = class UserProjects extends Abstract { * @apiSampleRequest /improvement-project/api/v1/userProjects/solutionDetails/5fba54dc5bf46b25a926bee5?taskId=347400e7-8a62-4dad-bc24-af7c5bd70ad1 * @apiParamExample {json} Request: { - "role" : "HM", + "role" : "HM,DEO", "state" : "236f5cff-c9af-4366-b0b6-253a1789766a", "district" : "1dcbc362-ec4c-4559-9081-e0c2864c2931", "school" : "c5726207-4f9f-4f45-91f1-3e9e8e84d824" @@ -492,7 +492,7 @@ module.exports = class UserProjects extends Abstract { "_id": "289d9558-b98f-41cf-81d3-92486f114a51" }, "profileInformation" : { - "role" : "HM", + "role" : "HM,DEO", "state" : "236f5cff-c9af-4366-b0b6-253a1789766a", "district" : "1dcbc362-ec4c-4559-9081-e0c2864c2931", "school" : "c5726207-4f9f-4f45-91f1-3e9e8e84d824" diff --git a/module/reports/helper.js b/module/reports/helper.js index c08c4475..5c428ded 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -344,12 +344,11 @@ module.exports = class ReportsHelper { query.userRole = { $in : [ "", - userRole + ...userRole.split(",") ] } } - let searchQuery = []; if (search !== "") { searchQuery = [{ "programInformation.name": new RegExp(search, 'i') }]; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index a2ef8625..f02d7bc5 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1624,7 +1624,7 @@ module.exports = class UserProjectsHelper { let totalCount = 0; let data = []; - + if( projects.success && projects.data ) { totalCount = projects.data.count; From 7680fbeb6946383b432d1995cc6760c6817cd527 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 15 Dec 2021 22:31:17 +0530 Subject: [PATCH 041/373] task sequence --- generics/constants/common.js | 3 + models/project-template-tasks.js | 3 + models/projects.js | 6 +- module/project/templateTasks/helper.js | 83 ++++++++++++++++++++++-- module/project/templates/helper.js | 90 +++++++++++++++++++++----- module/userProjects/helper.js | 31 +++++++++ 6 files changed, 194 insertions(+), 22 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index ccff6d26..fdd10b15 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -39,5 +39,8 @@ module.exports = { "LINK" : "link", "DEFAULT_SUBMISSION_REQUIRED" : 1, "STARTED" : "started", + "TASK_SEQUENCE" : "taskSequence", + "CHILDREN" : "children", + }; diff --git a/models/project-template-tasks.js b/models/project-template-tasks.js index e6b97458..d2d14db6 100644 --- a/models/project-template-tasks.js +++ b/models/project-template-tasks.js @@ -79,6 +79,9 @@ module.exports = { learningResources : { type : Array, default : [] + }, + sequenceNumber: { + type : String } } }; \ No newline at end of file diff --git a/models/projects.js b/models/projects.js index 305d66ec..b408d224 100644 --- a/models/projects.js +++ b/models/projects.js @@ -120,6 +120,10 @@ module.exports = { link : { type : String, index : true - } + }, + taskSequence : { + type : Array, + default : [] + }, } }; diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 6fc124e3..a2712ac6 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -76,7 +76,7 @@ module.exports = class ProjectTemplateTasksHelper { let tasksData = await projectTemplateTaskQueries.taskDocuments( filterData, - ["_id","children","externalId","projectTemplateId","parentId"] + ["_id","children","externalId","projectTemplateId","parentId", "taskSequence"] ); if( tasksData.length > 0 ) { @@ -94,7 +94,7 @@ module.exports = class ProjectTemplateTasksHelper { await projectTemplateQueries.templateDocument({ status : CONSTANTS.common.PUBLISHED, _id : projectTemplateId - },["_id","entityType","externalId"]); + },["_id","entityType","externalId", "taskSequence"]); if( !projectTemplate.length > 0 ) { throw { @@ -431,7 +431,7 @@ module.exports = class ProjectTemplateTasksHelper { } let pendingItems = []; - + let taskSequence = []; for ( let task = 0; task < tasks.length ; task ++ ) { let currentData = UTILS.valueParser(tasks[task]); currentData.createdBy = currentData.updatedBy = userId; @@ -441,6 +441,7 @@ module.exports = class ProjectTemplateTasksHelper { !csvData.data.tasks[currentData.parentTaskId] ) { pendingItems.push(currentData); + } else { if( csvData.data.tasks[currentData.externalId] ) { @@ -455,23 +456,29 @@ module.exports = class ProjectTemplateTasksHelper { csvData.data.solutionData ); + if (createdTask._SYSTEM_ID != ""){ + taskSequence.push(createdTask.externalId); + } + input.push(createdTask); } } } + let childTaskSequence = {}; if ( pendingItems && pendingItems.length > 0 ) { for ( let item = 0; item < pendingItems.length ; item ++ ) { let currentData = pendingItems[item]; + currentData.createdBy = currentData.updatedBy = userId; if( csvData.data.tasks[currentData.externalId] ) { currentData._SYSTEM_ID = CONSTANTS.apiResponses.PROJECT_TEMPLATE_TASK_EXISTS; input.push(currentData); } else { - + let createdTask = await this.createOrUpdateTask( currentData, csvData.data.template, @@ -479,11 +486,38 @@ module.exports = class ProjectTemplateTasksHelper { csvData.data.observationData ); + if ( createdTask._SYSTEM_ID != "" ) { + + if (!childTaskSequence.hasOwnProperty(currentData.parentTaskId)){ + childTaskSequence[currentData.parentTaskId] = new Array(); + } + childTaskSequence[currentData.parentTaskId].push(currentData.externalId); + } + input.push(createdTask); } } } + + if ( taskSequence && taskSequence.length > 0 ) { + await projectTemplateQueries.updateProjectTemplateDocument + ( + { _id : ObjectId(projectTemplateId) }, + { $set : { taskSequence : taskSequence } } + ) + } + + if ( childTaskSequence && Object.keys(childTaskSequence).length > 0 ) { + for( let pointerToTask in childTaskSequence ) { + await projectTemplateTaskQueries.updateTaskDocument + ( + { externalId : pointerToTask }, + { $set : { taskSequence : childTaskSequence[pointerToTask] } } + ) + } + + } input.push(null); @@ -544,6 +578,8 @@ module.exports = class ProjectTemplateTasksHelper { }) } + let updateChildTaskSequence = {}; + let updateTemplateTaskSequence = new Array(); for ( let task = 0; task < tasks.length ; task ++ ) { let currentData = UTILS.valueParser(tasks[task]); @@ -569,6 +605,19 @@ module.exports = class ProjectTemplateTasksHelper { true ); + if ( createdTask._SYSTEM_ID != "") { + + if ( currentData.parentTaskId != "" ) { + if ( !updateChildTaskSequence.hasOwnProperty(currentData.parentTaskId)){ + updateChildTaskSequence[currentData.parentTaskId] = new Array(); + } + + updateChildTaskSequence[currentData.parentTaskId].push(currentData.externalId); + }else{ + updateTemplateTaskSequence.push(currentData.externalId); + } + } + if( csvData.data.tasks[currentData._SYSTEM_ID].parentId && csvData.data.tasks[currentData._SYSTEM_ID].parentId.toString() !== createdTask._parentTaskId.toString() @@ -587,6 +636,32 @@ module.exports = class ProjectTemplateTasksHelper { input.push(createdTask); } + + let checkTemplateTaskSequence = true; + let templateTaskSequence = csvData.data.template.taskSequence; + + if ( templateTaskSequence ) { + checkTemplateTaskSequence = _.isEqual(templateTaskSequence, updateTemplateTaskSequence); + } + + if ( updateTemplateTaskSequence && updateTemplateTaskSequence.length > 0 && checkTemplateTaskSequence == false ) { + await projectTemplateQueries.updateProjectTemplateDocument + ( + { _id : ObjectId(projectTemplateId) }, + { $set : { taskSequence : updateTemplateTaskSequence } } + ) + } + + if ( updateChildTaskSequence && Object.keys(updateChildTaskSequence).length > 0 ) { + for( let pointerToTask in updateChildTaskSequence ) { + await projectTemplateTaskQueries.updateTaskDocument + ( + { externalId : pointerToTask }, + { $set : { taskSequence : updateChildTaskSequence[pointerToTask] } } + ) + } + + } input.push(null); diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 7ea53466..cc698eed 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1048,35 +1048,35 @@ module.exports = class ProjectTemplatesHelper { await projectTemplateQueries.templateDocument({ _id : templateId, status : CONSTANTS.common.PUBLISHED - },["tasks"]); + },["tasks", "taskSequence"]); let tasks = []; - if( templateDocument[0].tasks ) { + if ( templateDocument[0].taskSequence && templateDocument[0].taskSequence.length > 0 ) { + let projectionKey = CONSTANTS.common.TASK_SEQUENCE; let findQuery = { - _id : { - $in : templateDocument[0].tasks - }, - parentId : { $exists : false } + externalId : { + $in : templateDocument[0].taskSequence + } } - tasks = await projectTemplateTaskQueries.taskDocuments(findQuery,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); - for( let task = 0 ; task < tasks.length ; task ++ ) { - - if( tasks[task].children && tasks[task].children.length > 0 ) { - - let subTaskQuery = { + tasks = await _taskAndSubTaskinSequence(findQuery, projectionKey); + } else { + if ( templateDocument[0].tasks && templateDocument[0].tasks.length > 0 ){ + let projectionKey = CONSTANTS.common.CHILDREN; + if( templateDocument[0].tasks ) { + let findQuery = { _id : { - $in : tasks[task].children - } + $in : templateDocument[0].tasks + }, + parentId : { $exists : false } } - let subTasks = await projectTemplateTaskQueries.taskDocuments(subTaskQuery, "all", ["projectTemplateId","__v","projectTemplateExternalId"]); - - tasks[task].children = subTasks; + tasks = await _taskAndSubTaskinSequence(findQuery, projectionKey); } } + } return resolve(tasks); @@ -1174,3 +1174,59 @@ function _templateInformation(project) { } }) } + +/** + * Task and SubTask In Order. + * @method + * @name _taskAndSubTaskinSequence + * @param {Object} query - template Query. + * @param {String} projectionValue - children or taskSequence. + * @returns {Object} Task and SubTask information. +*/ + +function _taskAndSubTaskinSequence(query, projectionValue) { + + return new Promise(async (resolve, reject) => { + try { + + let tasks = []; + tasks = await projectTemplateTaskQueries.taskDocuments(query,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); + + for( let task = 0 ; task < tasks.length ; task++ ) { + if ( tasks[task][projectionValue] && tasks[task][projectionValue].length > 0 ) { + let subTaskQuery; + if ( projectionValue == CONSTANTS.common.CHILDREN ) { + subTaskQuery = { + "_id" : { + $in : tasks[task][projectionValue] + } + } + + } else { + subTaskQuery = { + "externalId" : { + $in : tasks[task][projectionValue] + } + } + } + + let subTasks = await projectTemplateTaskQueries.taskDocuments(subTaskQuery, "all", ["projectTemplateId","__v","projectTemplateExternalId"]); + tasks[task].children = subTasks; + } + } + + return resolve(tasks); + + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) + } + }) +} + + diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index a2ef8625..d823f5ac 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1788,6 +1788,7 @@ module.exports = class UserProjectsHelper { isATargetedSolution ); + if ( libraryProjects.data && !Object.keys(libraryProjects.data).length > 0 @@ -1963,6 +1964,36 @@ function _projectInformation(project) { project.programId = project.programInformation._id; project.programName = project.programInformation.name; } + //order task based on task sequence + if (project.taskSequence && project.taskSequence.length > 0) { + + let tasks = []; + let taskSequence = project.taskSequence ? project.taskSequence : []; + let projectTasks = project.tasks; + + for (let taskCounter = 0; taskCounter < taskSequence.length; taskCounter++) { + + let eachTask = projectTasks.find(item => item.externalId == taskSequence[taskCounter]); + if (eachTask && Object.keys(eachTask).length > 0) { + + let childTasks = []; + if (eachTask.children && eachTask.children.length > 0) { + + let childTaskSequence = eachTask.taskSequence; + for (let childTaskPointer = 0; childTaskPointer < childTaskSequence.length; childTaskPointer++) { + let eachChildTask = eachTask.children.find(childItem => childItem.externalId == childTaskSequence[childTaskPointer]); + childTasks.push(eachChildTask); + } + + eachTask.children = childTasks; + } + + tasks.push(eachTask); + } + } + + project.tasks = tasks; + } if (project.tasks && project.tasks.length > 0) { From 24e405bb708accd6ce69ff711c28837f601c980d Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 16 Dec 2021 15:34:51 +0530 Subject: [PATCH 042/373] bulkcreate fix --- module/project/templateTasks/helper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index a2712ac6..3f4196a4 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -431,7 +431,9 @@ module.exports = class ProjectTemplateTasksHelper { } let pendingItems = []; - let taskSequence = []; + let taskSequence = csvData.data.template.taskSequence && csvData.data.template.taskSequence.length > 0 + ? csvData.data.template.taskSequence: []; + for ( let task = 0; task < tasks.length ; task ++ ) { let currentData = UTILS.valueParser(tasks[task]); currentData.createdBy = currentData.updatedBy = userId; From 5af456ea3e5a4e548d189cff5852daba92ef3d7a Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Sun, 19 Dec 2021 23:16:56 +0530 Subject: [PATCH 043/373] check isDeletable and update parentTask --- generics/constants/api-responses.js | 3 +- module/project/templateTasks/helper.js | 94 +++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index b12790e6..2cf501bd 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -116,6 +116,7 @@ module.exports = { "PROJECT_TEMPLATE_DETAILS_FETCHED": "Successfully fetched project template details", "PROJECT_TEMPLATE_EXISTS_IN_SOLUTION" : "Project templates already exists in solution", "IMPORTED_PROJECTS_FETCHED" : "List of imported projects fetched", - "MIN_NO_OF_SUBMISSION_REQUIRED_MIS_MATCHED" : "minNoOfSubmissionsRequired should be 1 because allowMultipleAssessemts is false" + "MIN_NO_OF_SUBMISSION_REQUIRED_MIS_MATCHED" : "minNoOfSubmissionsRequired should be 1 because allowMultipleAssessemts is false", + "TASKS_MARKED_AS_ISDELETABLE_FALSE": "Successfully updated the tasks" }; diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 3f4196a4..092f51fa 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -76,7 +76,7 @@ module.exports = class ProjectTemplateTasksHelper { let tasksData = await projectTemplateTaskQueries.taskDocuments( filterData, - ["_id","children","externalId","projectTemplateId","parentId", "taskSequence"] + ["_id","children","externalId","projectTemplateId","parentId", "taskSequence", "hasSubTasks"] ); if( tasksData.length > 0 ) { @@ -434,14 +434,21 @@ module.exports = class ProjectTemplateTasksHelper { let taskSequence = csvData.data.template.taskSequence && csvData.data.template.taskSequence.length > 0 ? csvData.data.template.taskSequence: []; + let checkMandatoryTask = []; + for ( let task = 0; task < tasks.length ; task ++ ) { let currentData = UTILS.valueParser(tasks[task]); currentData.createdBy = currentData.updatedBy = userId; + if ( currentData.isDeletable != "" && currentData.isDeletable === "TRUE" ) { + checkMandatoryTask.push(currentData.externalId); + } + if( currentData["hasAParentTask"] === "YES" && !csvData.data.tasks[currentData.parentTaskId] ) { + pendingItems.push(currentData); } else { @@ -521,6 +528,12 @@ module.exports = class ProjectTemplateTasksHelper { } + if ( checkMandatoryTask && checkMandatoryTask.length > 0 ) { + + await this.checkAndUpdateParentTaskmandatory(checkMandatoryTask); + + } + input.push(null); } catch (error) { @@ -582,6 +595,7 @@ module.exports = class ProjectTemplateTasksHelper { let updateChildTaskSequence = {}; let updateTemplateTaskSequence = new Array(); + let checkMandatoryTask = []; for ( let task = 0; task < tasks.length ; task ++ ) { let currentData = UTILS.valueParser(tasks[task]); @@ -598,6 +612,10 @@ module.exports = class ProjectTemplateTasksHelper { } currentData.updatedBy = userId; + + if ( currentData.isDeletable != "" && currentData.isDeletable === "TRUE" ) { + checkMandatoryTask.push(currentData.externalId); + } let createdTask = await this.createOrUpdateTask( @@ -665,6 +683,12 @@ module.exports = class ProjectTemplateTasksHelper { } + if ( checkMandatoryTask && checkMandatoryTask.length > 0 ) { + + await this.checkAndUpdateParentTaskmandatory(checkMandatoryTask); + + } + input.push(null); } catch (error) { @@ -673,6 +697,74 @@ module.exports = class ProjectTemplateTasksHelper { }) } + /** + * check parent task is mandatory. + * @method + * @name checkAndUpdateParentTaskmandatory + * @param {Array} mandatoryTask - task external Ids. + * @returns {Object} tasks. + */ + + static checkAndUpdateParentTaskmandatory( taskIds = [] ) { + return new Promise(async (resolve, reject) => { + try { + + let updateParentTask = []; + + let taskData = await projectTemplateTaskQueries.taskDocuments( + { externalId : { $in : taskIds}, + hasSubTasks : true + }, + ["children"] + ); + + if ( taskData && taskData.length > 0 ) { + + for ( let eachTask = 0 ; eachTask < taskData.length ; eachTask ++ ) { + + let currentTask = taskData[eachTask]; + if (currentTask.children && currentTask.children.length > 0) { + + let childTasks = await projectTemplateTaskQueries.taskDocuments( + { _id : { $in : currentTask.children} + }, + ["isDeletable", "parentId"] + ); + + if ( childTasks && childTasks.length > 0 ) { + + childTasks.forEach( eachChildTask => { + console.log(eachChildTask._id) + if( eachChildTask.isDeletable === false && eachChildTask.parentId != "" ) { + updateParentTask.push(eachChildTask.parentId); + } + }); + } + } + } + + if ( updateParentTask && updateParentTask.length > 0 ) { + let updatedTasks = await projectTemplateTaskQueries.updateTaskDocument + ( + { _id : { $in : updateParentTask }}, + { $set : { isDeletable : false } } + ) + } + + } + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.TASKS_MARKED_AS_ISDELETABLE_FALSE, + data : updateParentTask + }) + + } catch (error) { + return reject(error); + } + }) + } + }; /** From cbeee4e2054b39fd427cec4ec9946b76f2985ae5 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 21 Dec 2021 15:54:08 +0530 Subject: [PATCH 044/373] template update and task update --- controllers/v1/project/templateTasks.js | 48 ++++++++++++++++++ controllers/v1/project/templates.js | 48 ++++++++++++++++++ generics/constants/api-responses.js | 5 +- module/project/templateTasks/helper.js | 67 +++++++++++++++++++++++++ module/project/templates/helper.js | 67 +++++++++++++++++++++++++ 5 files changed, 234 insertions(+), 1 deletion(-) diff --git a/controllers/v1/project/templateTasks.js b/controllers/v1/project/templateTasks.js index 50126526..cff6baab 100644 --- a/controllers/v1/project/templateTasks.js +++ b/controllers/v1/project/templateTasks.js @@ -138,4 +138,52 @@ module.exports = class ProjectTemplateTasks extends Abstract { }) } + /** + * @api {post} /improvement-project/api/v1/project/templateTasks/update/:taskId + * Update projects template. + * @apiVersion 1.0.0 + * @apiGroup Project Template Tasks + * @apiSampleRequest /improvement-project/api/v1/project/templateTasks/update/6006b5cca1a95727dbcdf648 + * @apiHeader {String} internal-access-token internal access token + * @apiHeader {String} X-authenticated-user-token Authenticity token + * @apiUse successBody + * @apiUse errorBody + * @apiParamExample {json} Response: + * { + * "status": 200, + "message": "template task updated successfully" + } + */ + + /** + * Update project templates task + * @method + * @name update + * @returns {JSON} returns uploaded project template task. + */ + + async update(req) { + return new Promise(async (resolve, reject) => { + try { + + let projectTemplateTask = await projectTemplateTasksHelper.update( + req.params._id, + req.body, + req.userDetails.id + ); + + projectTemplateTask.result = projectTemplateTask.data; + + return resolve(projectTemplateTask); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + }; diff --git a/controllers/v1/project/templates.js b/controllers/v1/project/templates.js index 903b2f86..9cfea766 100644 --- a/controllers/v1/project/templates.js +++ b/controllers/v1/project/templates.js @@ -687,4 +687,52 @@ module.exports = class ProjectTemplates extends Abstract { }) } + /** + * @api {post} /improvement-project/api/v1/project/templates/update/:templateId + * Update projects template. + * @apiVersion 1.0.0 + * @apiGroup Project Templates + * @apiSampleRequest /improvement-project/api/v1/project/templates/update/6006b5cca1a95727dbcdf648 + * @apiHeader {String} internal-access-token internal access token + * @apiHeader {String} X-authenticated-user-token Authenticity token + * @apiUse successBody + * @apiUse errorBody + * @apiParamExample {json} Response: + * { + * "status": 200, + "message": "template updated successfully" + } + */ + + /** + * Update project templates + * @method + * @name update + * @returns {JSON} returns uploaded project template. + */ + + async update(req) { + return new Promise(async (resolve, reject) => { + try { + + let projectTemplate = await projectTemplatesHelper.update( + req.params._id, + req.body, + req.userDetails.id + ); + + projectTemplate.result = projectTemplate.data; + + return resolve(projectTemplate); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + }; diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 2cf501bd..65fa6d52 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -117,6 +117,9 @@ module.exports = { "PROJECT_TEMPLATE_EXISTS_IN_SOLUTION" : "Project templates already exists in solution", "IMPORTED_PROJECTS_FETCHED" : "List of imported projects fetched", "MIN_NO_OF_SUBMISSION_REQUIRED_MIS_MATCHED" : "minNoOfSubmissionsRequired should be 1 because allowMultipleAssessemts is false", - "TASKS_MARKED_AS_ISDELETABLE_FALSE": "Successfully updated the tasks" + "TASKS_MARKED_AS_ISDELETABLE_FALSE": "Successfully updated the tasks", + "TEMPLATE_TASK_NOT_UPDATED": "Could not updated template task", + "PROJECT_TEMPLATE_UPDATED" : "Successfully updated project template", + "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", }; diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 092f51fa..e7fde9e6 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -765,6 +765,73 @@ module.exports = class ProjectTemplateTasksHelper { }) } + /** + * Task update. + * @method + * @name update + * @param {String} taskId - Task id. + * @param {Object} taskData - template task updation data + * @param {String} userId - logged in user id. + * @returns {Array} Project templates task data. + */ + + static update( taskId, taskData, userId ) { + return new Promise(async (resolve, reject) => { + try { + + let findQuery = {}; + + let validateTaskId = UTILS.isValidMongoId(taskId); + + if( validateTaskId ) { + findQuery["_id"] = taskId; + } else { + findQuery["externalId"] = taskId; + } + + let taskDocument = await projectTemplateTaskQueries.taskDocuments(findQuery, ["_id"]); + + if ( !taskDocument.length > 0 ) { + throw { + status : HTTP_STATUS_CODE.bad_request.status, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_TASKS_NOT_FOUND + } + } + + let updateObject = { + "$set" : {} + }; + + let taskUpdateData = taskData; + + Object.keys(taskUpdateData).forEach(updationData=>{ + updateObject["$set"][updationData] = taskUpdateData[updationData]; + }); + + updateObject["$set"]["updatedBy"] = userId; + + let taskUpdatedData = await projectTemplateTaskQueries.findOneAndUpdate({ + _id : taskDocument[0]._id + }, updateObject, { new : true }); + + if( !taskUpdatedData._id ) { + throw { + message : constants.apiResponses.TEMPLATE_TASK_NOT_UPDATED + } + } + + return resolve({ + success : true, + data : taskUpdatedData, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_TASK_UPDATED + }); + + } catch (error) { + return reject(error); + } + }) + } + }; /** diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index cc698eed..a9eb59ee 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1087,6 +1087,73 @@ module.exports = class ProjectTemplatesHelper { }); } + /** + * Template update. + * @method + * @name update + * @param {String} templateId - Project template id. + * @param {Object} templateData - template updation data + * @param {String} userId - logged in user id. + * @returns {Array} Project templates data. + */ + + static update( templateId, templateData, userId ) { + return new Promise(async (resolve, reject) => { + try { + + let findQuery = {}; + + let validateTemplateId = UTILS.isValidMongoId(templateId); + + if( validateTemplateId ) { + findQuery["_id"] = templateId; + } else { + findQuery["externalId"] = templateId; + } + + let templateDocument = await projectTemplateQueries.templateDocument(findQuery, ["_id"]); + + if ( !templateDocument.length > 0 ) { + throw { + status : HTTP_STATUS_CODE.bad_request.status, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND + } + } + + let updateObject = { + "$set" : {} + }; + + let templateUpdateData = templateData; + + Object.keys(templateUpdateData).forEach(updationData=>{ + updateObject["$set"][updationData] = templateUpdateData[updationData]; + }); + + updateObject["$set"]["updatedBy"] = userId; + + let templateUpdatedData = await projectTemplateQueries.findOneAndUpdate({ + _id : templateDocument[0]._id + }, updateObject, { new : true }); + + if( !templateUpdatedData._id ) { + throw { + message : constants.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED + } + } + + return resolve({ + success : true, + data : templateUpdatedData, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_UPDATED + }); + + } catch (error) { + return reject(error); + } + }) + } + }; /** From b466e0228c22e260839170b583d088ac1a16a41e Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 21 Dec 2021 18:23:40 +0530 Subject: [PATCH 045/373] remove console log --- module/project/templateTasks/helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index e7fde9e6..5298b12d 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -734,7 +734,6 @@ module.exports = class ProjectTemplateTasksHelper { if ( childTasks && childTasks.length > 0 ) { childTasks.forEach( eachChildTask => { - console.log(eachChildTask._id) if( eachChildTask.isDeletable === false && eachChildTask.parentId != "" ) { updateParentTask.push(eachChildTask.parentId); } From 4580292b61f9b1168266c411f9bb2824052860ee Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Wed, 29 Dec 2021 15:29:58 +0530 Subject: [PATCH 046/373] push projects to kafka --- .env.sample | 3 ++- generics/kafka/producers.js | 30 +++++++++++++++++++++++++++++- module/userProjects/helper.js | 10 +++++++++- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/.env.sample b/.env.sample index e8d6d82c..38553e55 100644 --- a/.env.sample +++ b/.env.sample @@ -26,4 +26,5 @@ KAFKA_URL = "172.31.0.4:9092" KAFKA_GROUP_ID = "projects" // Kafka group id # SUBMISSION TOPIC -SUBMISSION_TOPIC = "dev.sl.projects.submissions" // Kafka topic name for pushing projects submissions \ No newline at end of file +SUBMISSION_TOPIC = "dev.sl.projects.submissions" // Kafka topic name for pushing projects submissions +IMPROVEMENT_PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.imp_submissions" // project submission topic \ No newline at end of file diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index ee376c23..55d7f4c2 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -7,6 +7,7 @@ // Dependencies const kafkaCommunicationsOnOff = (!process.env.KAFKA_COMMUNICATIONS_ON_OFF || process.env.KAFKA_COMMUNICATIONS_ON_OFF != "OFF") ? "ON" : "OFF"; +const improvementProjectSubmissionTopic = (process.env.IMPROVEMENT_PROJECT_SUBMISSION_TOPIC && process.env.IMPROVEMENT_PROJECT_SUBMISSION_TOPIC != "OFF") ? process.env.IMPROVEMENT_PROJECT_SUBMISSION_TOPIC : "sl-improvement-project-submission-dev"; /** * Push improvement projects to kafka. @@ -32,6 +33,8 @@ const pushProjectToKafka = function (message) { }) } + + /** * Push message to kafka. * @function @@ -69,7 +72,32 @@ const pushMessageToKafka = function(payload) { }) } + +/** + * Push improvement projects to kafka. + * @function + * @name pushImrovementProjectToKafka + * @param {Object} message - Message data. +*/ + +const pushImrovementProjectToKafka = function (message) { + return new Promise(async (resolve, reject) => { + try { + + let kafkaPushStatus = await pushMessageToKafka([{ + topic: improvementProjectSubmissionTopic, + messages: JSON.stringify(message) + }]); + return resolve(kafkaPushStatus); + + } catch (error) { + return reject(error); + } + }) +} + module.exports = { - pushProjectToKafka : pushProjectToKafka + pushProjectToKafka : pushProjectToKafka, + pushImrovementProjectToKafka : pushImrovementProjectToKafka }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9605855b..b50d1d63 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -19,6 +19,8 @@ const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategorie const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); +const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); + /** * UserProjectsHelper * @class @@ -339,6 +341,8 @@ module.exports = class UserProjectsHelper { } } + await kafkaProducersHelper.pushImrovementProjectToKafka(projectUpdated); + return resolve({ success: true, message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, @@ -1130,6 +1134,9 @@ module.exports = class UserProjectsHelper { projectCreation.data.userRoleInformtion = userRoleInformation; let project = await projectQueries.createProject(projectCreation.data); + + await kafkaProducersHelper.pushImrovementProjectToKafka(project); + projectId = project._id; } } @@ -1309,7 +1316,6 @@ module.exports = class UserProjectsHelper { createProject["entityInformation"] = entityInformation.data[0]; createProject.entityId = entityInformation.data[0]._id; } - if (createNewProgramAndSolution) { let programAndSolutionInformation = @@ -1392,6 +1398,8 @@ module.exports = class UserProjectsHelper { createProject ); + await kafkaProducersHelper.pushImrovementProjectToKafka(userProject); + if (!userProject._id) { throw { message: CONSTANTS.apiResponses.USER_PROJECT_NOT_CREATED, From aec8d66f1481ee52d652896dc56bd5d88a0a32a1 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Wed, 29 Dec 2021 17:12:07 +0530 Subject: [PATCH 047/373] pr comments changes --- .env.sample | 2 +- generics/kafka/producers.js | 30 +++--------------------------- module/userProjects/helper.js | 6 +++--- 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/.env.sample b/.env.sample index 38553e55..81fa286c 100644 --- a/.env.sample +++ b/.env.sample @@ -27,4 +27,4 @@ KAFKA_GROUP_ID = "projects" # SUBMISSION TOPIC SUBMISSION_TOPIC = "dev.sl.projects.submissions" // Kafka topic name for pushing projects submissions -IMPROVEMENT_PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.imp_submissions" // project submission topic \ No newline at end of file +PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.submissions" // project submission topic \ No newline at end of file diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index 55d7f4c2..b32404aa 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -7,7 +7,7 @@ // Dependencies const kafkaCommunicationsOnOff = (!process.env.KAFKA_COMMUNICATIONS_ON_OFF || process.env.KAFKA_COMMUNICATIONS_ON_OFF != "OFF") ? "ON" : "OFF"; -const improvementProjectSubmissionTopic = (process.env.IMPROVEMENT_PROJECT_SUBMISSION_TOPIC && process.env.IMPROVEMENT_PROJECT_SUBMISSION_TOPIC != "OFF") ? process.env.IMPROVEMENT_PROJECT_SUBMISSION_TOPIC : "sl-improvement-project-submission-dev"; +const projectSubmissionTopic = (process.env.PROJECT_SUBMISSION_TOPIC && process.env.PROJECT_SUBMISSION_TOPIC != "OFF") ? process.env.PROJECT_SUBMISSION_TOPIC : "sl-improvement-project-submission-dev"; /** * Push improvement projects to kafka. @@ -21,7 +21,7 @@ const pushProjectToKafka = function (message) { try { let kafkaPushStatus = await pushMessageToKafka([{ - topic: process.env.NOTIFICATIONS_TOPIC, + topic: projectSubmissionTopic, messages: JSON.stringify(message) }]); @@ -73,31 +73,7 @@ const pushMessageToKafka = function(payload) { } -/** - * Push improvement projects to kafka. - * @function - * @name pushImrovementProjectToKafka - * @param {Object} message - Message data. -*/ - -const pushImrovementProjectToKafka = function (message) { - return new Promise(async (resolve, reject) => { - try { - - let kafkaPushStatus = await pushMessageToKafka([{ - topic: improvementProjectSubmissionTopic, - messages: JSON.stringify(message) - }]); - return resolve(kafkaPushStatus); - - } catch (error) { - return reject(error); - } - }) -} - module.exports = { - pushProjectToKafka : pushProjectToKafka, - pushImrovementProjectToKafka : pushImrovementProjectToKafka + pushProjectToKafka : pushProjectToKafka }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index b50d1d63..e2f6b348 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -341,7 +341,7 @@ module.exports = class UserProjectsHelper { } } - await kafkaProducersHelper.pushImrovementProjectToKafka(projectUpdated); + await kafkaProducersHelper.pushProjectToKafka(projectUpdated); return resolve({ success: true, @@ -1135,7 +1135,7 @@ module.exports = class UserProjectsHelper { let project = await projectQueries.createProject(projectCreation.data); - await kafkaProducersHelper.pushImrovementProjectToKafka(project); + await kafkaProducersHelper.pushProjectToKafka(project); projectId = project._id; } @@ -1398,7 +1398,7 @@ module.exports = class UserProjectsHelper { createProject ); - await kafkaProducersHelper.pushImrovementProjectToKafka(userProject); + await kafkaProducersHelper.pushProjectToKafka(userProject); if (!userProject._id) { throw { From 72bc34354697ce4eea9d46522001efca8992e990 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Fri, 31 Dec 2021 14:29:08 +0530 Subject: [PATCH 048/373] push to kafka when user improt project from library --- module/userProjects/helper.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index e2f6b348..0b9b33fe 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1922,6 +1922,8 @@ module.exports = class UserProjectsHelper { _.omit(libraryProjects.data, ["_id"]) ); + await kafkaProducersHelper.pushProjectToKafka(projectCreation); + if (requestedData.rating && requestedData.rating > 0) { await projectTemplatesHelper.ratings( projectTemplateId, From dc42e062d61ca5d5445ed2c4db952775075647a3 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 5 Jan 2022 19:06:10 +0530 Subject: [PATCH 049/373] rename project model key --- models/projects.js | 2 +- module/userProjects/helper.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/models/projects.js b/models/projects.js index b408d224..2fd3da19 100644 --- a/models/projects.js +++ b/models/projects.js @@ -107,7 +107,7 @@ module.exports = { index : true }, appInformation : Object, - userRoleInformtion : Object, + userRoleInformation : Object, hasAcceptedTAndC : { type : Boolean, default : false diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index e2f6b348..93ab3816 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -475,7 +475,7 @@ module.exports = class UserProjectsHelper { * @returns {Object} */ - static details(projectId, userId,userRoleInformtion = {}) { + static details(projectId, userId,userRoleInformation = {}) { return new Promise(async (resolve, reject) => { try { @@ -504,13 +504,13 @@ module.exports = class UserProjectsHelper { } } - if (Object.keys(userRoleInformtion).length > 0) { + if (Object.keys(userRoleInformation).length > 0) { - if (!projectDetails[0].userRoleInformtion || !Object.keys(projectDetails[0].userRoleInformtion).length > 0) { + if (!projectDetails[0].userRoleInformation || !Object.keys(projectDetails[0].userRoleInformation).length > 0) { await projectQueries.findOneAndUpdate({ _id: projectId },{ - $set: {userRoleInformtion: userRoleInformtion} + $set: {userRoleInformation: userRoleInformation} }); } } @@ -1131,7 +1131,7 @@ module.exports = class UserProjectsHelper { projectCreation.data.status = CONSTANTS.common.NOT_STARTED_STATUS; projectCreation.data.lastDownloadedAt = new Date(); - projectCreation.data.userRoleInformtion = userRoleInformation; + projectCreation.data.userRoleInformation = userRoleInformation; let project = await projectQueries.createProject(projectCreation.data); @@ -1391,7 +1391,7 @@ module.exports = class UserProjectsHelper { createProject["lastDownloadedAt"] = new Date(); if (data.profileInformation) { - createProject.userRoleInformtion = data.profileInformation; + createProject.userRoleInformation = data.profileInformation; } let userProject = await projectQueries.createProject( From 89311a921609234cd4fc70fa2672ad189a9002a1 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Mon, 10 Jan 2022 13:02:55 +0530 Subject: [PATCH 050/373] project read api added --- controllers/v1/userProjects.js | 34 ++++++++++++++++++++++++ generics/middleware/authenticator.js | 7 ++++- module/userProjects/helper.js | 39 ++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 1c2bbf23..c642c0db 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -956,5 +956,39 @@ module.exports = class UserProjects extends Abstract { } }) } + + + /** + * Get project details. + * @method + * @name read + * @param {Object} req - request data. + * @param {String} req.params._id - project Id. + * @returns {JSON} project details + */ + + async read(req) { + return new Promise(async (resolve, reject) => { + try { + + const projectDetails = await userProjectsHelper.read( + req.params._id + ); + + return resolve({ + status: projectDetails.status, + message: projectDetails.message, + result: projectDetails.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } }; \ No newline at end of file diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index f5160731..a5934143 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -61,7 +61,7 @@ module.exports = async function (req, res, next, token = "") { return; } - let internalAccessApiPaths = ["/templates/bulkCreate"]; + let internalAccessApiPaths = ["/templates/bulkCreate","/userProjects/read"]; let performInternalAccessTokenCheck = false; await Promise.all(internalAccessApiPaths.map(async function (path) { if (req.path.includes(path)) { @@ -69,6 +69,7 @@ module.exports = async function (req, res, next, token = "") { } })); + console.log("performInternalAccessTokenCheck",performInternalAccessTokenCheck); if (performInternalAccessTokenCheck) { if (req.headers["internal-access-token"] !== process.env.INTERNAL_ACCESS_TOKEN) { rspObj.errCode = CONSTANTS.apiResponses.TOKEN_MISSING_CODE; @@ -76,6 +77,10 @@ module.exports = async function (req, res, next, token = "") { rspObj.responseCode = HTTP_STATUS_CODE['unauthorized'].status; return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } + if(!token){ + next(); + return; + } } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 02e854c0..b409773b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1950,6 +1950,45 @@ module.exports = class UserProjectsHelper { }) } + /** + * get project details. + * @method + * @name read + * @param {String} projectId - project id. + * @returns {Object} Project details. + */ + + static read(projectId) { + return new Promise(async (resolve, reject) => { + try { + + const projectDetails = await projectQueries.projectDocument({ + _id: projectId, + }, "all"); + + if (!projectDetails.length > 0) { + + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND + } + } + return resolve( { + success: true, + message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, + data: projectDetails[0] + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + }; /** From 4eee27d96e092efe8e8225096fd58d82c7254ccc Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Mon, 10 Jan 2022 13:03:35 +0530 Subject: [PATCH 051/373] console removed --- generics/middleware/authenticator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index a5934143..37f7806b 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -69,7 +69,6 @@ module.exports = async function (req, res, next, token = "") { } })); - console.log("performInternalAccessTokenCheck",performInternalAccessTokenCheck); if (performInternalAccessTokenCheck) { if (req.headers["internal-access-token"] !== process.env.INTERNAL_ACCESS_TOKEN) { rspObj.errCode = CONSTANTS.apiResponses.TOKEN_MISSING_CODE; From a48c9276214439a040bcc48f363105bc2ab88aa5 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Mon, 10 Jan 2022 13:08:11 +0530 Subject: [PATCH 052/373] validators updated --- module/userProjects/validator/v1.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index 81c87ce9..7a0b2f6b 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -25,6 +25,10 @@ module.exports = (req) => { }, share : function () { req.checkParams('_id').exists().withMessage("required project id"); + }, + read : function () { + req.checkParams('_id').exists().withMessage("required project id") + .isMongoId().withMessage("Invalid project id"); } } From a312c993d1e47bf69d95fb01da8e56b40ab1ac14 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 11 Jan 2022 11:09:09 +0530 Subject: [PATCH 053/373] submission fix --- module/userProjects/helper.js | 56 +++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 02e854c0..f1733f95 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -807,15 +807,61 @@ module.exports = class UserProjectsHelper { try { let update = {}; + let tasksUpdated; - update["tasks.$." + "submissions"] = updatedData - - const tasksUpdated = - await projectQueries.findOneAndUpdate({ + let projectDocument = await projectQueries.projectDocument( + { _id: projectId, "tasks._id": taskId - }, { $push: update }); + }, [ + "tasks.$.submissions" + ]); + + let tasks = projectDocument[0].tasks; + if ( tasks && tasks.length > 0 ) { + tasks = projectDocument[0].tasks[0]; + } + + let submissions = tasks.submissions; + let pushToSubmissionArray = false; + + if ( !submissions && !submissions.length > 0 ){ + pushToSubmissionArray = true; + } + + let checkSubmissionExist = submissions.filter(submission => submission._id == updatedData._id); + + if ( !checkSubmissionExist.length > 0 ) { + pushToSubmissionArray = true; + } + + if ( pushToSubmissionArray === true ) { + + update["tasks.$." + "submissions"] = updatedData; + tasksUpdated = + await projectQueries.findOneAndUpdate({ + _id: projectId, + "tasks._id": taskId + }, { $push: update }); + + } else { + + const index = submissions.indexOf(checkSubmissionExist[0]); + + if ( submissions[index].status !== CONSTANTS.common.COMPLETED_STATUS ) { + submissions[index] = updatedData; + } + + update["tasks.$." + "submissions"] = submissions; + tasksUpdated = + await projectQueries.findOneAndUpdate({ + _id: projectId, + "tasks._id": taskId + }, { $set: update }); + + } + return resolve(tasksUpdated); } catch (error) { From 1ced30bbfde22edb8be17089c86c34880ca60d04 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Wed, 12 Jan 2022 10:24:26 +0530 Subject: [PATCH 054/373] datapipeline api added --- controllers/v1/dataPipeline.js | 73 ++++++++++++++++++++++++++++ controllers/v1/userProjects.js | 34 ------------- generics/middleware/authenticator.js | 4 +- module/dataPipeline/helper.js | 44 +++++++++++++++++ module/dataPipeline/validator/v1.js | 22 +++++++++ module/userProjects/helper.js | 7 +-- module/userProjects/validator/v1.js | 4 -- 7 files changed, 145 insertions(+), 43 deletions(-) create mode 100644 controllers/v1/dataPipeline.js create mode 100644 module/dataPipeline/helper.js create mode 100644 module/dataPipeline/validator/v1.js diff --git a/controllers/v1/dataPipeline.js b/controllers/v1/dataPipeline.js new file mode 100644 index 00000000..c2d33f20 --- /dev/null +++ b/controllers/v1/dataPipeline.js @@ -0,0 +1,73 @@ +/** + * name : userProjects.js + * author : Aman + * created-date : 20-July-2020 + * Description : User Projects related information. + */ + +// Dependencies +const csv = require('csvtojson'); +const dataPipelineHelper = require(MODULES_BASE_PATH + "/dataPipeline/helper"); + + /** + * UserProjects + * @class +*/ + +module.exports = class DataPipeline { + + /** + * @apiDefine errorBody + * @apiError {String} status 4XX,5XX + * @apiError {String} message Error + */ + + /** + * @apiDefine successBody + * @apiSuccess {String} status 200 + * @apiSuccess {String} result Data + */ + + // constructor() { + // super("projects"); + // } + + static get name() { + return "dataPipeline"; + } + + /** + * Get project details. + * @method + * @name read + * @param {Object} req - request data. + * @param {String} req.params._id - project Id. + * @returns {JSON} project details + */ + + async userProject(req) { + return new Promise(async (resolve, reject) => { + try { + + console.log("req.params._id",req.params._id); + const projectDetails = await dataPipelineHelper.userProject( + req.params._id + ); + + return resolve({ + status: projectDetails.status, + message: projectDetails.message, + result: projectDetails.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + +}; \ No newline at end of file diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index c642c0db..1c2bbf23 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -956,39 +956,5 @@ module.exports = class UserProjects extends Abstract { } }) } - - - /** - * Get project details. - * @method - * @name read - * @param {Object} req - request data. - * @param {String} req.params._id - project Id. - * @returns {JSON} project details - */ - - async read(req) { - return new Promise(async (resolve, reject) => { - try { - - const projectDetails = await userProjectsHelper.read( - req.params._id - ); - - return resolve({ - status: projectDetails.status, - message: projectDetails.message, - result: projectDetails.data - }); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } }; \ No newline at end of file diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index 37f7806b..235ad80a 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -49,7 +49,7 @@ module.exports = async function (req, res, next, token = "") { // Allow search endpoints for non-logged in users. let guestAccess = false; - let guestAccessPaths = []; + let guestAccessPaths = ["/dataPipeline/"]; await Promise.all(guestAccessPaths.map(async function (path) { if (req.path.includes(path)) { guestAccess = true; @@ -61,7 +61,7 @@ module.exports = async function (req, res, next, token = "") { return; } - let internalAccessApiPaths = ["/templates/bulkCreate","/userProjects/read"]; + let internalAccessApiPaths = ["/templates/bulkCreate"]; let performInternalAccessTokenCheck = false; await Promise.all(internalAccessApiPaths.map(async function (path) { if (req.path.includes(path)) { diff --git a/module/dataPipeline/helper.js b/module/dataPipeline/helper.js new file mode 100644 index 00000000..78115ca8 --- /dev/null +++ b/module/dataPipeline/helper.js @@ -0,0 +1,44 @@ +/** + * name : helper.js + * author : Rakesh + * created-date : 11-Jun-2020 + * Description : DataPipeline helper functionality. + */ + +// Dependencies + +const UserProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); + +/** + * dataPipelineHelper + * @class + */ + +module.exports = class dataPipelineHelper { + + /** + * get uset project details. + * @method + * @name userProject + * @param {String} projectId - project id. + * @returns {Object} Project details. + */ + + static userProject(projectId) { + return new Promise(async (resolve, reject) => { + try { + + const projectDetails = await UserProjectsHelper.userProject(projectId); + return resolve(projectDetails); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + +} \ No newline at end of file diff --git a/module/dataPipeline/validator/v1.js b/module/dataPipeline/validator/v1.js new file mode 100644 index 00000000..37d4cff5 --- /dev/null +++ b/module/dataPipeline/validator/v1.js @@ -0,0 +1,22 @@ +/** + * name : v1.js + * author : Rakesh + * created-date : 11-Jan-2020 + * Description : DataPipeline. + */ + + module.exports = (req) => { + + let dataPipeLineValidator = { + + userProject : function () { + req.checkParams('_id').exists().withMessage("required project id") + .isMongoId().withMessage("Invalid project id"); + } + } + + if (dataPipeLineValidator[req.params.method]) { + dataPipeLineValidator[req.params.method](); + } + +}; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index b409773b..3f5a3353 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1953,12 +1953,12 @@ module.exports = class UserProjectsHelper { /** * get project details. * @method - * @name read + * @name userProject * @param {String} projectId - project id. * @returns {Object} Project details. */ - static read(projectId) { + static userProject(projectId) { return new Promise(async (resolve, reject) => { try { @@ -1972,7 +1972,8 @@ module.exports = class UserProjectsHelper { status: HTTP_STATUS_CODE["bad_request"].status, message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND } - } + } + return resolve( { success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index 7a0b2f6b..81c87ce9 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -25,10 +25,6 @@ module.exports = (req) => { }, share : function () { req.checkParams('_id').exists().withMessage("required project id"); - }, - read : function () { - req.checkParams('_id').exists().withMessage("required project id") - .isMongoId().withMessage("Invalid project id"); } } From f9b32940202d547c60d703021a9f621459afd64b Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Wed, 12 Jan 2022 11:59:50 +0530 Subject: [PATCH 055/373] pr changes --- controllers/v1/dataPipeline.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/controllers/v1/dataPipeline.js b/controllers/v1/dataPipeline.js index c2d33f20..2abd4293 100644 --- a/controllers/v1/dataPipeline.js +++ b/controllers/v1/dataPipeline.js @@ -1,16 +1,15 @@ /** - * name : userProjects.js - * author : Aman + * name : dataPipeline.js + * author : Rakesh * created-date : 20-July-2020 - * Description : User Projects related information. + * Description : DataPipeline related information. */ // Dependencies -const csv = require('csvtojson'); const dataPipelineHelper = require(MODULES_BASE_PATH + "/dataPipeline/helper"); /** - * UserProjects + * DataPipeline * @class */ @@ -27,10 +26,6 @@ module.exports = class DataPipeline { * @apiSuccess {String} status 200 * @apiSuccess {String} result Data */ - - // constructor() { - // super("projects"); - // } static get name() { return "dataPipeline"; @@ -49,7 +44,6 @@ module.exports = class DataPipeline { return new Promise(async (resolve, reject) => { try { - console.log("req.params._id",req.params._id); const projectDetails = await dataPipelineHelper.userProject( req.params._id ); From 927b11c3a990b1828eb47bc2e5e414694d77de35 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 12 Jan 2022 13:31:31 +0530 Subject: [PATCH 056/373] project submission fix --- module/userProjects/helper.js | 67 ++++++++++++++--------------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index f1733f95..c6b503c2 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -806,62 +806,47 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - let update = {}; - let tasksUpdated; + let updateSubmission = []; let projectDocument = await projectQueries.projectDocument( { _id: projectId, "tasks._id": taskId }, [ - "tasks.$.submissions" + "tasks" ]); - let tasks = projectDocument[0].tasks; - if ( tasks && tasks.length > 0 ) { - tasks = projectDocument[0].tasks[0]; - } - - let submissions = tasks.submissions; - let pushToSubmissionArray = false; - - if ( !submissions && !submissions.length > 0 ){ - pushToSubmissionArray = true; - } - - let checkSubmissionExist = submissions.filter(submission => submission._id == updatedData._id); - - if ( !checkSubmissionExist.length > 0 ) { - pushToSubmissionArray = true; + let currentTask = projectDocument[0].tasks.find(task => task._id == taskId); + let submissions = currentTask.submissions && currentTask.submissions.length > 0 ? currentTask.submissions : [] ; + + // if submission array is empty + if ( !submissions && !submissions.length > 0 ) { + updateSubmission.push(updatedData); } + + // submission not exist + let checkSubmissionExist = submissions.findIndex(submission => submission._id == updatedData._id); - if ( pushToSubmissionArray === true ) { - - update["tasks.$." + "submissions"] = updatedData; + if ( checkSubmissionExist == -1 ) { - tasksUpdated = - await projectQueries.findOneAndUpdate({ - _id: projectId, - "tasks._id": taskId - }, { $push: update }); + updateSubmission = submissions; + updateSubmission.push(updatedData); } else { + //submission exist + submissions[checkSubmissionExist] = updatedData; + updateSubmission = submissions; + } - const index = submissions.indexOf(checkSubmissionExist[0]); - - if ( submissions[index].status !== CONSTANTS.common.COMPLETED_STATUS ) { - submissions[index] = updatedData; - } - - update["tasks.$." + "submissions"] = submissions; - tasksUpdated = - await projectQueries.findOneAndUpdate({ - _id: projectId, - "tasks._id": taskId - }, { $set: update }); + let tasksUpdated = await projectQueries.findOneAndUpdate({ + "_id": projectId, + "tasks._id": taskId + }, { + $set: { + "tasks.$.submissions": updateSubmission + } + }); - } - return resolve(tasksUpdated); } catch (error) { From dc1e38c69c3b5a6b70a855a8ca92471d5af2a6ea Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 21 Jan 2022 10:54:44 +0530 Subject: [PATCH 057/373] template detail api change --- config/connections.js | 8 +- controllers/v1/project/templates.js | 11 +- databaseQueries/projectTemplates.js | 2 - generics/constants/api-responses.js | 2 +- generics/constants/endpoints.js | 3 +- generics/middleware/authenticator.js | 2 +- generics/services/core.js | 65 ++++++- module/project/templates/helper.js | 223 +++++++++++++++++------ module/project/templates/validator/v1.js | 6 +- package.json | 2 +- 10 files changed, 254 insertions(+), 70 deletions(-) diff --git a/config/connections.js b/config/connections.js index 4084cb2a..1150e881 100644 --- a/config/connections.js +++ b/config/connections.js @@ -24,9 +24,9 @@ const mongodb_connect = function () { * @name kafka_connect */ -const kafka_connect = function() { - global.kafkaClient = require("./kafka")(); -}; +//const kafka_connect = function() { + //global.kafkaClient = require("./kafka")(); +//}; // Configuration data. @@ -35,6 +35,6 @@ const configuration = { }; mongodb_connect(); -kafka_connect(); +//kafka_connect(); module.exports = configuration; diff --git a/controllers/v1/project/templates.js b/controllers/v1/project/templates.js index 9cfea766..c2d53430 100644 --- a/controllers/v1/project/templates.js +++ b/controllers/v1/project/templates.js @@ -32,6 +32,7 @@ module.exports = class ProjectTemplates extends Abstract { constructor() { super("project-templates"); } + /** * @api {post} /improvement-project/api/v1/project/templates/bulkCreate @@ -666,12 +667,16 @@ module.exports = class ProjectTemplates extends Abstract { async details(req) { return new Promise(async (resolve, reject) => { + try { - + (req.params._id) ? req.params._id=req.params._id : req.params._id=""; + (req.query.link) ? req.query.link=req.query.link : req.query.link=""; + let userId=""; + //req.userDetails.userInformation.userId let projectTemplatesDetails = await projectTemplatesHelper.details( - req.params._id, - req.userDetails.userInformation.userId + req.params._id,req.query.link, + userId ); projectTemplatesDetails.result = projectTemplatesDetails.data; diff --git a/databaseQueries/projectTemplates.js b/databaseQueries/projectTemplates.js index fbf6ff0d..cbfdcabf 100644 --- a/databaseQueries/projectTemplates.js +++ b/databaseQueries/projectTemplates.js @@ -53,7 +53,6 @@ module.exports = class ProjectTemplates { ) { return new Promise(async (resolve, reject) => { try { - let queryObject = (filterData != "all") ? filterData : {}; let projection = {} @@ -68,7 +67,6 @@ module.exports = class ProjectTemplates { projection[field] = 0; }); } - let templates = await database.models.projectTemplates.find( queryObject, diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 65fa6d52..7342e1e3 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -121,5 +121,5 @@ module.exports = { "TEMPLATE_TASK_NOT_UPDATED": "Could not updated template task", "PROJECT_TEMPLATE_UPDATED" : "Successfully updated project template", "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", - + "PROJECT_TEMPLATE_FETCH_ERROR" : "Faild to fetch data due to invalid input", }; diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index ace4f25d..5b4d3077 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -43,5 +43,6 @@ module.exports = { SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION : "/v1/solutions/detailsBasedOnRoleAndLocation", LIST_ENTITIES_BY_LOCATION_IDS : "/v1/entities/listByLocationIds", CREATE_IMPROVEMENT_PROJECT_SOLUTION : "/v1/solutions/create", - PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport" + PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport", + GET_LIST_SOLUTION : "/v1/solutions/getList" }; diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index 235ad80a..031b42ac 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -49,7 +49,7 @@ module.exports = async function (req, res, next, token = "") { // Allow search endpoints for non-logged in users. let guestAccess = false; - let guestAccessPaths = ["/dataPipeline/"]; + let guestAccessPaths = ["/dataPipeline/","/templates/details"]; await Promise.all(guestAccessPaths.map(async function (path) { if (req.path.includes(path)) { guestAccess = true; diff --git a/generics/services/core.js b/generics/services/core.js index 4e8ca33b..a2d52d13 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -721,6 +721,68 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution }) } +/** + * List of solutions. + * @function + * @name solutionsDocument + * @param {Object} filterData - Filter data. + * @param {Array} projection - Projected data. + * @param {Array} skipFields - Field to skip. + * @returns {JSON} - List of solutions. +*/ + +const solutionsDocuments = function ( + filterData = "all", + projection = "all", + skipFields = "none" +) { + return new Promise(async (resolve, reject) => { + try { + + const url = ML_CORE_URL + CONSTANTS.endpoints.GET_LIST_SOLUTION; + + const options = { + headers : { + "content-type": "application/json", + "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, + }, + json : { + query : filterData, + projection : projection, + skipFields : skipFields + } + }; + + request.post(url,options,kendraCallback); + + function kendraCallback(err, data) { + + let result = { + success : true + }; + + if (err) { + result.success = false; + } else { + + let response = data.body; + + if( response.status === HTTP_STATUS_CODE['ok'].status ) { + result["data"] = response.result; + } else { + result.success = false; + } + } + + return resolve(result); + } + + } catch (error) { + return reject(error); + } + }) +} + module.exports = { entityTypesDocuments : entityTypesDocuments, rolesDocuments : rolesDocuments, @@ -734,6 +796,7 @@ module.exports = { createSolution: createSolution, solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, - getDownloadableUrl : getDownloadableUrl + getDownloadableUrl : getDownloadableUrl, + solutionsDocuments : solutionsDocuments }; diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index a9eb59ee..f9d65817 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -22,6 +22,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); + module.exports = class ProjectTemplatesHelper { /** @@ -957,74 +958,190 @@ module.exports = class ProjectTemplatesHelper { * @name details * @param {String} templateId - Project template id. * @param {String} userId - logged in user id. + * @params {String} link - solution link. * @returns {Array} Project templates data. */ - static details( templateId,userId ) { + static details( templateId,link,userId ) { return new Promise(async (resolve, reject) => { try { - - let findQuery = {}; - - let validateTemplateId = UTILS.isValidMongoId(templateId); - - if( validateTemplateId ) { - findQuery["_id"] = templateId; - } else { - findQuery["externalId"] = templateId; - } - - let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", - [ - "ratings", - "noOfRatings", - "averageRating", - "parentTemplateId", - "userId", - "createdBy", - "updatedBy", - "createdAt", - "updatedAt", - "__v" - ]); - - if ( !templateData.length > 0 ) { - throw { - status : HTTP_STATUS_CODE.bad_request.status, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND + if(templateId==="" && link===""){ + throw{ + status:HTTP_STATUS_CODE.bad_request.status, + message:CONSTANTS.apiResponses.PROJECT_TEMPLATE_FETCH_ERROR } } + //getting template data when templateId(req.params_id) is provided + if(templateId){ + let findQuery = {}; - if (templateData[0].tasks && templateData[0].tasks.length > 0) { - templateData[0].tasks = - await this.tasksAndSubTasks(templateData[0]._id); + let validateTemplateId = UTILS.isValidMongoId(templateId); + if( validateTemplateId ) { + findQuery["_id"] = templateId; + } else { + findQuery["externalId"] = templateId; + } + let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", + [ + "ratings", + "noOfRatings", + "averageRating", + "parentTemplateId", + "userId", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt", + "__v" + ]); + + if ( !templateData.length > 0 ) { + throw { + status : HTTP_STATUS_CODE.bad_request.status, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND + } + } + + if (templateData[0].tasks && templateData[0].tasks.length > 0) { + templateData[0].tasks = + await this.tasksAndSubTasks(templateData[0]._id); + } + + let result = await _templateInformation(templateData[0]) + if( !result.success ) { + return resolve(result); + } + + if( !templateData[0].isReusable ) { + + templateData[0].projectId = ""; + + let project = await projectQueries.projectDocument({ + userId : userId, + projectTemplateId : templateData[0]._id + },["_id"]); + + if(project && project.length > 0){ + templateData[0].projectId = project[0]._id; + } + } + + return resolve({ + success : false, + data : result.data, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED + }); } - let result = await _templateInformation(templateData[0]) - - if( !result.success ) { - return resolve(result); - } + //get data when link is given + if(link){ + + let queryData={}; + queryData["link"]=link; + + let solutionDocument = + await coreService.solutionsDocuments( + queryData, + [ + "_id", + "name", + "programId", + "programName", + "externalId", + "projectTemplateId", + "link" + ], + "none" + ); - if( !templateData[0].isReusable ) { + if( !solutionDocument.success || solutionDocument.data.length===0 ) { + throw { + message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } + } - templateData[0].projectId = ""; + let solutiondata=solutionDocument.data; + let templateId=solutiondata.map(function(id){ + return id.projectTemplateId + }); + templateId=templateId.toString(); + if(!templateId){ + // throw { + // message : CONSTANTS.apiResponses.MISSING_PROJECT_TEMPLATE_ID, + // status : HTTP_STATUS_CODE['bad_request'].status, + // result:"checking" + // } + return resolve({ + success : false, + data : solutiondata, + message : CONSTANTS.apiResponses.MISSING_PROJECT_TEMPLATE_ID + }); + } + //for templateId: is available + let findQuery = {}; + + let validateTemplateId = UTILS.isValidMongoId(templateId); + if( validateTemplateId ) { + findQuery["_id"] = templateId; + }else { + findQuery["externalId"] = templateId; + } + let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", + [ + "ratings", + "noOfRatings", + "averageRating", + "parentTemplateId", + "userId", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt", + "__v" + ]); + + if ( !templateData.length > 0 ) { + throw { + status : HTTP_STATUS_CODE.bad_request.status, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND + } + + } + + if (templateData[0].tasks && templateData[0].tasks.length > 0) { + templateData[0].tasks = + await this.tasksAndSubTasks(templateData[0]._id); + } + + let result = await _templateInformation(templateData[0]) + if( !result.success ) { + return resolve(result); + } + + if( !templateData[0].isReusable ) { + + templateData[0].projectId = ""; + + let project = await projectQueries.projectDocument({ + userId : userId, + projectTemplateId : templateData[0]._id + },["_id"]); + + if(project && project.length > 0){ + templateData[0].projectId = project[0]._id; + } + } + result.sdata=solutiondata; + return resolve({ + success : false, + data : result, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED + }); - let project = await projectQueries.projectDocument({ - userId : userId, - projectTemplateId : templateData[0]._id - },["_id"]); - if(project && project.length > 0){ - templateData[0].projectId = project[0]._id; - } } - - return resolve({ - success : false, - data : result.data, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED - }); + } catch (error) { return reject(error); diff --git a/module/project/templates/validator/v1.js b/module/project/templates/validator/v1.js index c21952fe..321c0fc6 100644 --- a/module/project/templates/validator/v1.js +++ b/module/project/templates/validator/v1.js @@ -13,9 +13,9 @@ module.exports = (req) => { req.checkParams('_id').exists().withMessage("required project template id"); req.checkQuery('solutionId').exists().withMessage("required solution id"); }, - details : function () { - req.checkParams("_id").exists().withMessage("required project template external id"); - } + // details : function () { + // req.checkParams("_id").exists().withMessage("required project template external id"); + // } } if (projectTemplateValidator[req.params.method]) { diff --git a/package.json b/package.json index 665c3f8c..a7afd220 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "xml-js": "^1.6.11", "chai": "^4.2.0", "chai-http": "^4.3.0", - "mocha": "^6.2.2" + "mocha": "^6.2.2" }, "devDependencies": { "grunt-apidoc": "^0.11.0", From 251f306f81aed69c46d591c91252ade784caf91c Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 21 Jan 2022 15:47:52 +0530 Subject: [PATCH 058/373] conflict changes-first --- config/connections.js | 6 +++--- controllers/v1/project/templates.js | 11 ++++++----- generics/constants/api-responses.js | 2 +- generics/constants/endpoints.js | 2 +- module/project/templates/helper.js | 14 +++++--------- module/project/templates/validator/v1.js | 3 --- 6 files changed, 16 insertions(+), 22 deletions(-) diff --git a/config/connections.js b/config/connections.js index 1150e881..bb2ec2fc 100644 --- a/config/connections.js +++ b/config/connections.js @@ -24,9 +24,9 @@ const mongodb_connect = function () { * @name kafka_connect */ -//const kafka_connect = function() { - //global.kafkaClient = require("./kafka")(); -//}; +// const kafka_connect = function() { +// global.kafkaClient = require("./kafka")(); +// }; // Configuration data. diff --git a/controllers/v1/project/templates.js b/controllers/v1/project/templates.js index c2d53430..6c8f600c 100644 --- a/controllers/v1/project/templates.js +++ b/controllers/v1/project/templates.js @@ -669,14 +669,15 @@ module.exports = class ProjectTemplates extends Abstract { return new Promise(async (resolve, reject) => { try { - (req.params._id) ? req.params._id=req.params._id : req.params._id=""; - (req.query.link) ? req.query.link=req.query.link : req.query.link=""; - let userId=""; + //req.userDetails.userInformation.userId?req.userDetails.userInformation.userId:""; + //console.log(req.userDetails,"checking the condition"); //req.userDetails.userInformation.userId + //let userId = ""; let projectTemplatesDetails = await projectTemplatesHelper.details( - req.params._id,req.query.link, - userId + req.params._id?req.params._id:"", + req.query.link?req.query.link:"", + req.userDetails && req.userDetails.userInformation && req.userDetails.userInformation.userId?req.userDetails.userInformation.userId:"" ); projectTemplatesDetails.result = projectTemplatesDetails.data; diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 7342e1e3..4665e6d7 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -121,5 +121,5 @@ module.exports = { "TEMPLATE_TASK_NOT_UPDATED": "Could not updated template task", "PROJECT_TEMPLATE_UPDATED" : "Successfully updated project template", "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", - "PROJECT_TEMPLATE_FETCH_ERROR" : "Faild to fetch data due to invalid input", + "PROJECT_TEMPLATE_FETCH_ERROR" : "TemplateId or Link either one is required", }; diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 5b4d3077..427e5702 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -44,5 +44,5 @@ module.exports = { LIST_ENTITIES_BY_LOCATION_IDS : "/v1/entities/listByLocationIds", CREATE_IMPROVEMENT_PROJECT_SOLUTION : "/v1/solutions/create", PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport", - GET_LIST_SOLUTION : "/v1/solutions/getList" + GET_LIST_SOLUTION : "/v1/solutions/getList" }; diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index f9d65817..4b98d207 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -962,9 +962,10 @@ module.exports = class ProjectTemplatesHelper { * @returns {Array} Project templates data. */ - static details( templateId,link,userId ) { + static details( templateId="",link="",userId="" ) { return new Promise(async (resolve, reject) => { try { + if(templateId==="" && link===""){ throw{ status:HTTP_STATUS_CODE.bad_request.status, @@ -1036,8 +1037,8 @@ module.exports = class ProjectTemplatesHelper { //get data when link is given if(link){ - let queryData={}; - queryData["link"]=link; + let queryData = {}; + queryData["link"] =link; let solutionDocument = await coreService.solutionsDocuments( @@ -1066,12 +1067,7 @@ module.exports = class ProjectTemplatesHelper { return id.projectTemplateId }); templateId=templateId.toString(); - if(!templateId){ - // throw { - // message : CONSTANTS.apiResponses.MISSING_PROJECT_TEMPLATE_ID, - // status : HTTP_STATUS_CODE['bad_request'].status, - // result:"checking" - // } + if( !templateId ){ return resolve({ success : false, data : solutiondata, diff --git a/module/project/templates/validator/v1.js b/module/project/templates/validator/v1.js index 321c0fc6..71d4cd83 100644 --- a/module/project/templates/validator/v1.js +++ b/module/project/templates/validator/v1.js @@ -13,9 +13,6 @@ module.exports = (req) => { req.checkParams('_id').exists().withMessage("required project template id"); req.checkQuery('solutionId').exists().withMessage("required solution id"); }, - // details : function () { - // req.checkParams("_id").exists().withMessage("required project template external id"); - // } } if (projectTemplateValidator[req.params.method]) { From 911a4910c24ace82ae524e57b12c53728c628ce3 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 21 Jan 2022 16:33:52 +0530 Subject: [PATCH 059/373] comment resolve-two --- generics/constants/api-responses.js | 1 + module/project/templates/helper.js | 232 ++++++++++++++-------------- 2 files changed, 113 insertions(+), 120 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 4665e6d7..19bfb89d 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -122,4 +122,5 @@ module.exports = { "PROJECT_TEMPLATE_UPDATED" : "Successfully updated project template", "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", "PROJECT_TEMPLATE_FETCH_ERROR" : "TemplateId or Link either one is required", + "GOT_SOLUTIONS_NO_TEMPLATE_ID" : "Solution fetched successfully. But projectTemplateId is empty" }; diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 4b98d207..cd8e2708 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -972,68 +972,7 @@ module.exports = class ProjectTemplatesHelper { message:CONSTANTS.apiResponses.PROJECT_TEMPLATE_FETCH_ERROR } } - //getting template data when templateId(req.params_id) is provided - if(templateId){ - let findQuery = {}; - - let validateTemplateId = UTILS.isValidMongoId(templateId); - if( validateTemplateId ) { - findQuery["_id"] = templateId; - } else { - findQuery["externalId"] = templateId; - } - let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", - [ - "ratings", - "noOfRatings", - "averageRating", - "parentTemplateId", - "userId", - "createdBy", - "updatedBy", - "createdAt", - "updatedAt", - "__v" - ]); - - if ( !templateData.length > 0 ) { - throw { - status : HTTP_STATUS_CODE.bad_request.status, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND - } - } - - if (templateData[0].tasks && templateData[0].tasks.length > 0) { - templateData[0].tasks = - await this.tasksAndSubTasks(templateData[0]._id); - } - - let result = await _templateInformation(templateData[0]) - if( !result.success ) { - return resolve(result); - } - - if( !templateData[0].isReusable ) { - - templateData[0].projectId = ""; - - let project = await projectQueries.projectDocument({ - userId : userId, - projectTemplateId : templateData[0]._id - },["_id"]); - - if(project && project.length > 0){ - templateData[0].projectId = project[0]._id; - } - } - - return resolve({ - success : false, - data : result.data, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED - }); - } - + let findQuery = {}; //get data when link is given if(link){ @@ -1051,9 +990,8 @@ module.exports = class ProjectTemplatesHelper { "externalId", "projectTemplateId", "link" - ], - "none" - ); + ] + ); if( !solutionDocument.success || solutionDocument.data.length===0 ) { throw { @@ -1063,80 +1001,134 @@ module.exports = class ProjectTemplatesHelper { } let solutiondata=solutionDocument.data; - let templateId=solutiondata.map(function(id){ - return id.projectTemplateId - }); - templateId=templateId.toString(); + let templateId=solutiondata[0].projectTemplateId if( !templateId ){ return resolve({ success : false, data : solutiondata, - message : CONSTANTS.apiResponses.MISSING_PROJECT_TEMPLATE_ID + message : CONSTANTS.apiResponses.GOT_SOLUTIONS_NO_TEMPLATE_ID }); } - //for templateId: is available - let findQuery = {}; - + } + if(templateId){ let validateTemplateId = UTILS.isValidMongoId(templateId); if( validateTemplateId ) { - findQuery["_id"] = templateId; - }else { - findQuery["externalId"] = templateId; + findQuery["_id"] = templateId; + } else { + findQuery["externalId"] = templateId; } - let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", - [ - "ratings", - "noOfRatings", - "averageRating", - "parentTemplateId", - "userId", - "createdBy", - "updatedBy", - "createdAt", - "updatedAt", - "__v" - ]); + } + //for templateId: is available + + // let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", + // [ + // "ratings", + // "noOfRatings", + // "averageRating", + // "parentTemplateId", + // "userId", + // "createdBy", + // "updatedBy", + // "createdAt", + // "updatedAt", + // "__v" + // ]); - if ( !templateData.length > 0 ) { - throw { - status : HTTP_STATUS_CODE.bad_request.status, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND - } + // if ( !templateData.length > 0 ) { + // throw { + // status : HTTP_STATUS_CODE.bad_request.status, + // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND + // } - } + // } - if (templateData[0].tasks && templateData[0].tasks.length > 0) { - templateData[0].tasks = - await this.tasksAndSubTasks(templateData[0]._id); - } + // if (templateData[0].tasks && templateData[0].tasks.length > 0) { + // templateData[0].tasks = + // await this.tasksAndSubTasks(templateData[0]._id); + // } - let result = await _templateInformation(templateData[0]) - if( !result.success ) { - return resolve(result); - } + // let result = await _templateInformation(templateData[0]) + // if( !result.success ) { + // return resolve(result); + // } - if( !templateData[0].isReusable ) { + // if( !templateData[0].isReusable ) { - templateData[0].projectId = ""; + // templateData[0].projectId = ""; - let project = await projectQueries.projectDocument({ - userId : userId, - projectTemplateId : templateData[0]._id - },["_id"]); + // let project = await projectQueries.projectDocument({ + // userId : userId, + // projectTemplateId : templateData[0]._id + // },["_id"]); - if(project && project.length > 0){ - templateData[0].projectId = project[0]._id; - } - } - result.sdata=solutiondata; - return resolve({ - success : false, - data : result, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED - }); + // if(project && project.length > 0){ + // templateData[0].projectId = project[0]._id; + // } + // } + // result.sdata=solutiondata; + // return resolve({ + // success : false, + // data : result, + // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED + // }); - } + + //getting template data when templateId(req.params_id) is provided + + // let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", + // [ + // "ratings", + // "noOfRatings", + // "averageRating", + // "parentTemplateId", + // "userId", + // "createdBy", + // "updatedBy", + // "createdAt", + // "updatedAt", + // "__v" + // ]); + + // if ( !templateData.length > 0 ) { + // throw { + // status : HTTP_STATUS_CODE.bad_request.status, + // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND + // } + // } + + // if (templateData[0].tasks && templateData[0].tasks.length > 0) { + // templateData[0].tasks = + // await this.tasksAndSubTasks(templateData[0]._id); + // } + + // let result = await _templateInformation(templateData[0]) + // if( !result.success ) { + // return resolve(result); + // } + + // if( !templateData[0].isReusable ) { + + // templateData[0].projectId = ""; + + // let project = await projectQueries.projectDocument({ + // userId : userId, + // projectTemplateId : templateData[0]._id + // },["_id"]); + + // if(project && project.length > 0){ + // templateData[0].projectId = project[0]._id; + // } + // } + + // return resolve({ + // success : false, + // data : result.data, + // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED + // }); + // } + + } catch (error) { From 69e6903bb917643177395328fdaacdd0cfa4850a Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 21 Jan 2022 17:30:05 +0530 Subject: [PATCH 060/373] command removed --- config/connections.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/connections.js b/config/connections.js index bb2ec2fc..4084cb2a 100644 --- a/config/connections.js +++ b/config/connections.js @@ -24,9 +24,9 @@ const mongodb_connect = function () { * @name kafka_connect */ -// const kafka_connect = function() { -// global.kafkaClient = require("./kafka")(); -// }; +const kafka_connect = function() { + global.kafkaClient = require("./kafka")(); +}; // Configuration data. @@ -35,6 +35,6 @@ const configuration = { }; mongodb_connect(); -//kafka_connect(); +kafka_connect(); module.exports = configuration; From 5456100a2fd0f73f18cae6d1877f2c5a22b2dede Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 21 Jan 2022 19:03:44 +0530 Subject: [PATCH 061/373] helper resolved --- module/project/templates/helper.js | 160 ++++++++++------------------- 1 file changed, 52 insertions(+), 108 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index cd8e2708..74fe2602 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -965,7 +965,7 @@ module.exports = class ProjectTemplatesHelper { static details( templateId="",link="",userId="" ) { return new Promise(async (resolve, reject) => { try { - + let solutionsResult = {}; if(templateId==="" && link===""){ throw{ status:HTTP_STATUS_CODE.bad_request.status, @@ -1001,7 +1001,7 @@ module.exports = class ProjectTemplatesHelper { } let solutiondata=solutionDocument.data; - let templateId=solutiondata[0].projectTemplateId + templateId=solutiondata[0].projectTemplateId if( !templateId ){ return resolve({ success : false, @@ -1009,8 +1009,10 @@ module.exports = class ProjectTemplatesHelper { message : CONSTANTS.apiResponses.GOT_SOLUTIONS_NO_TEMPLATE_ID }); } + solutionsResult = solutiondata; } - if(templateId){ + + if( templateId ){ let validateTemplateId = UTILS.isValidMongoId(templateId); if( validateTemplateId ) { findQuery["_id"] = templateId; @@ -1018,118 +1020,60 @@ module.exports = class ProjectTemplatesHelper { findQuery["externalId"] = templateId; } } - //for templateId: is available - - // let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", - // [ - // "ratings", - // "noOfRatings", - // "averageRating", - // "parentTemplateId", - // "userId", - // "createdBy", - // "updatedBy", - // "createdAt", - // "updatedAt", - // "__v" - // ]); - - // if ( !templateData.length > 0 ) { - // throw { - // status : HTTP_STATUS_CODE.bad_request.status, - // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND - // } - - // } - - // if (templateData[0].tasks && templateData[0].tasks.length > 0) { - // templateData[0].tasks = - // await this.tasksAndSubTasks(templateData[0]._id); - // } - - // let result = await _templateInformation(templateData[0]) - // if( !result.success ) { - // return resolve(result); - // } - - // if( !templateData[0].isReusable ) { - - // templateData[0].projectId = ""; - - // let project = await projectQueries.projectDocument({ - // userId : userId, - // projectTemplateId : templateData[0]._id - // },["_id"]); - - // if(project && project.length > 0){ - // templateData[0].projectId = project[0]._id; - // } - // } - // result.sdata=solutiondata; - // return resolve({ - // success : false, - // data : result, - // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED - // }); - + //getting template data using templateId + + let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", + [ + "ratings", + "noOfRatings", + "averageRating", + "parentTemplateId", + "userId", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt", + "__v" + ] + ); - //getting template data when templateId(req.params_id) is provided - - // let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", - // [ - // "ratings", - // "noOfRatings", - // "averageRating", - // "parentTemplateId", - // "userId", - // "createdBy", - // "updatedBy", - // "createdAt", - // "updatedAt", - // "__v" - // ]); - - // if ( !templateData.length > 0 ) { - // throw { - // status : HTTP_STATUS_CODE.bad_request.status, - // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND - // } - // } - - // if (templateData[0].tasks && templateData[0].tasks.length > 0) { - // templateData[0].tasks = - // await this.tasksAndSubTasks(templateData[0]._id); - // } + if ( !templateData.length > 0 ) { + throw { + status : HTTP_STATUS_CODE.bad_request.status, + message :CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND + } + } + + if (templateData[0].tasks && templateData[0].tasks.length > 0) { + templateData[0].tasks = + await this.tasksAndSubTasks(templateData[0]._id); + } - // let result = await _templateInformation(templateData[0]) - // if( !result.success ) { - // return resolve(result); - // } + let result = await _templateInformation(templateData[0]) + if( !result.success ) { + return resolve(result); + } - // if( !templateData[0].isReusable ) { + if( !templateData[0].isReusable && userId !== "") { - // templateData[0].projectId = ""; - - // let project = await projectQueries.projectDocument({ - // userId : userId, - // projectTemplateId : templateData[0]._id - // },["_id"]); + templateData[0].projectId = ""; - // if(project && project.length > 0){ - // templateData[0].projectId = project[0]._id; - // } - // } + let project = await projectQueries.projectDocument({ + userId : userId, + projectTemplateId : templateData[0]._id + },["_id"]); - // return resolve({ - // success : false, - // data : result.data, - // message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED - // }); - // } - - - + if(project && project.length > 0){ + templateData[0].projectId = project[0]._id; + } + } + result.slnData=solutionsResult; + return resolve({ + success : false, + data : result, + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED + }); } catch (error) { return reject(error); From 745a71213fdf3b0ff22b523c58aa5aaba3d45a4f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 24 Jan 2022 16:28:43 +0530 Subject: [PATCH 062/373] formated and comments removed --- controllers/v1/project/templates.js | 11 ++++------- generics/constants/api-responses.js | 2 +- module/project/templates/helper.js | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/controllers/v1/project/templates.js b/controllers/v1/project/templates.js index 6c8f600c..9d46f314 100644 --- a/controllers/v1/project/templates.js +++ b/controllers/v1/project/templates.js @@ -669,15 +669,12 @@ module.exports = class ProjectTemplates extends Abstract { return new Promise(async (resolve, reject) => { try { - //req.userDetails.userInformation.userId?req.userDetails.userInformation.userId:""; - //console.log(req.userDetails,"checking the condition"); - //req.userDetails.userInformation.userId - //let userId = ""; + let projectTemplatesDetails = await projectTemplatesHelper.details( - req.params._id?req.params._id:"", - req.query.link?req.query.link:"", - req.userDetails && req.userDetails.userInformation && req.userDetails.userInformation.userId?req.userDetails.userInformation.userId:"" + req.params._id ? req.params._id : "", + req.query.link ? req.query.link : "", + req.userDetails && req.userDetails.userInformation && req.userDetails.userInformation.userId ? req.userDetails.userInformation.userId : "" ); projectTemplatesDetails.result = projectTemplatesDetails.data; diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 19bfb89d..51463ab1 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -122,5 +122,5 @@ module.exports = { "PROJECT_TEMPLATE_UPDATED" : "Successfully updated project template", "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", "PROJECT_TEMPLATE_FETCH_ERROR" : "TemplateId or Link either one is required", - "GOT_SOLUTIONS_NO_TEMPLATE_ID" : "Solution fetched successfully. But projectTemplateId is empty" + "TEMPLATE_ID_NOT_FOUND_IN_SOLUTION" : "Could not found templateId in solution" }; diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 74fe2602..f5a03282 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -966,7 +966,7 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { let solutionsResult = {}; - if(templateId==="" && link===""){ + if(templateId == "" && link == ""){ throw{ status:HTTP_STATUS_CODE.bad_request.status, message:CONSTANTS.apiResponses.PROJECT_TEMPLATE_FETCH_ERROR @@ -993,7 +993,7 @@ module.exports = class ProjectTemplatesHelper { ] ); - if( !solutionDocument.success || solutionDocument.data.length===0 ) { + if( !solutionDocument.success || solutionDocument.data.length === 0 ) { throw { message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, status : HTTP_STATUS_CODE['bad_request'].status @@ -1006,7 +1006,7 @@ module.exports = class ProjectTemplatesHelper { return resolve({ success : false, data : solutiondata, - message : CONSTANTS.apiResponses.GOT_SOLUTIONS_NO_TEMPLATE_ID + message : CONSTANTS.apiResponses.TEMPLATE_ID_NOT_FOUND_IN_SOLUTION }); } solutionsResult = solutiondata; From a1f4ceff869104d8de819b577904cd0a346798b3 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 24 Jan 2022 16:56:14 +0530 Subject: [PATCH 063/373] formatted --- generics/constants/api-responses.js | 2 +- module/project/templates/helper.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 51463ab1..fb5d0ed4 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -121,6 +121,6 @@ module.exports = { "TEMPLATE_TASK_NOT_UPDATED": "Could not updated template task", "PROJECT_TEMPLATE_UPDATED" : "Successfully updated project template", "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", - "PROJECT_TEMPLATE_FETCH_ERROR" : "TemplateId or Link either one is required", + "TEMPLATE_ID_OR_LINK_REQUIRED" : "TemplateId or Link either one is required", "TEMPLATE_ID_NOT_FOUND_IN_SOLUTION" : "Could not found templateId in solution" }; diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index f5a03282..6ee4b852 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -969,12 +969,12 @@ module.exports = class ProjectTemplatesHelper { if(templateId == "" && link == ""){ throw{ status:HTTP_STATUS_CODE.bad_request.status, - message:CONSTANTS.apiResponses.PROJECT_TEMPLATE_FETCH_ERROR + message:CONSTANTS.apiResponses.TEMPLATE_ID_OR_LINK_REQUIRED } } let findQuery = {}; //get data when link is given - if(link){ + if( link ){ let queryData = {}; queryData["link"] =link; @@ -1000,7 +1000,7 @@ module.exports = class ProjectTemplatesHelper { } } - let solutiondata=solutionDocument.data; + let solutiondata = solutionDocument.data; templateId=solutiondata[0].projectTemplateId if( !templateId ){ return resolve({ From b63e22b879d622e5ea253f9a4ac7d6180ef16892 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 24 Jan 2022 17:02:22 +0530 Subject: [PATCH 064/373] result modified --- module/project/templates/helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 6ee4b852..e9762222 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1068,10 +1068,10 @@ module.exports = class ProjectTemplatesHelper { templateData[0].projectId = project[0]._id; } } - result.slnData=solutionsResult; + result.data=solutionsResult; return resolve({ success : false, - data : result, + data : result.data, message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED }); From 46293e21c6635d94d21f949d09abed308bcb1678 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 24 Jan 2022 17:28:19 +0530 Subject: [PATCH 065/373] formatted --- module/project/templates/helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index e9762222..b5fa0b9d 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -962,7 +962,7 @@ module.exports = class ProjectTemplatesHelper { * @returns {Array} Project templates data. */ - static details( templateId="",link="",userId="" ) { + static details( templateId="", link="", userId="" ) { return new Promise(async (resolve, reject) => { try { let solutionsResult = {}; @@ -1001,7 +1001,7 @@ module.exports = class ProjectTemplatesHelper { } let solutiondata = solutionDocument.data; - templateId=solutiondata[0].projectTemplateId + templateId = solutiondata[0].projectTemplateId; if( !templateId ){ return resolve({ success : false, From 7d58a896c8f572bf7616af58f6be749b54da4ef5 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 24 Jan 2022 17:40:12 +0530 Subject: [PATCH 066/373] formated --- generics/services/core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/services/core.js b/generics/services/core.js index a2d52d13..5da4fb66 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -797,6 +797,6 @@ module.exports = { solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, getDownloadableUrl : getDownloadableUrl, - solutionsDocuments : solutionsDocuments + solutionsDocuments : solutionsDocuments }; From ff96d98a57f766a68283f89ece7dcc72816d883a Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 25 Jan 2022 01:53:34 +0530 Subject: [PATCH 067/373] status change for sync, detail, add, importFromLibrary apis --- generics/constants/common.js | 1 + generics/helpers/utils.js | 48 ++++++++++++++++++++++++++++++++++- models/projects.js | 2 +- module/userProjects/helper.js | 38 ++++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index fdd10b15..a6fc6e2f 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -21,6 +21,7 @@ module.exports = { "COMPLETED_STATUS" : "completed", "INPROGRESS_STATUS" : "inProgress", "NOT_STARTED_STATUS" : "notStarted", + "SUBMITTED_STATUS" : "submitted", "OBSERVATION" : "observation", "PUBLISHED_STATUS" : "published", "LEAD_ASSESSOR" : "LEAD_ASSESSOR", diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 95af57e0..335e593b 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -170,6 +170,50 @@ function epochTime() { return currentDate; } +/** + * Convert Project Status + * @function + * @name convertProjectStatus + * @returns {String} returns converted project status + */ + +function convertProjectStatus(status) { + + let convertedStatus; + + if ( status == CONSTANTS.common.NOT_STARTED_STATUS ) { + convertedStatus = CONSTANTS.common.STARTED; + } else if ( status == CONSTANTS.common.COMPLETED_STATUS ) { + convertedStatus = CONSTANTS.common.SUBMITTED_STATUS; + } else { + convertedStatus = status; + } + + return convertedStatus; +} + +/** + * Revert Project Status For Older App + * @function + * @name revertProjectStatus + * @returns {String} returns reverted project status + */ + +function revertProjectStatus(status) { + + let revertedStatus; + + if ( status == CONSTANTS.common.STARTED ) { + revertedStatus = CONSTANTS.common.NOT_STARTED_STATUS; + } else if ( status == CONSTANTS.common.SUBMITTED_STATUS ) { + revertedStatus = CONSTANTS.common.COMPLETED_STATUS; + } else { + revertedStatus = status; + } + + return revertedStatus; +} + module.exports = { camelCaseToTitleCase : camelCaseToTitleCase, lowerCase : lowerCase, @@ -179,5 +223,7 @@ module.exports = { convertStringToBoolean : convertStringToBoolean, getAllBooleanDataFromModels : getAllBooleanDataFromModels, epochTime : epochTime, - isValidMongoId : isValidMongoId + isValidMongoId : isValidMongoId, + convertProjectStatus : convertProjectStatus, + revertProjectStatus : revertProjectStatus }; diff --git a/models/projects.js b/models/projects.js index 2fd3da19..08c98120 100644 --- a/models/projects.js +++ b/models/projects.js @@ -30,7 +30,7 @@ module.exports = { }, status : { type : String, - default : "notStarted", + default : "started", index: true }, lastDownloadedAt : Date, diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4aca33dc..b4040265 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -322,6 +322,8 @@ module.exports = class UserProjectsHelper { } } + updateProject.status = UTILS.convertProjectStatus(data.status); + let projectUpdated = await projectQueries.findOneAndUpdate( { @@ -1160,7 +1162,7 @@ module.exports = class UserProjectsHelper { } - projectCreation.data.status = CONSTANTS.common.NOT_STARTED_STATUS; + projectCreation.data.status = CONSTANTS.common.STARTED; projectCreation.data.lastDownloadedAt = new Date(); projectCreation.data.userRoleInformation = userRoleInformation; @@ -1178,6 +1180,11 @@ module.exports = class UserProjectsHelper { userRoleInformation ); + projectDetails.data.status = _checkAppVersionAndConvertProjectStatus( + appVersion, + projectDetails.data.status + ); + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, @@ -1390,7 +1397,6 @@ module.exports = class UserProjectsHelper { let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); - Object.keys(data).forEach(updateData => { if ( !createProject[updateData] && @@ -1425,6 +1431,8 @@ module.exports = class UserProjectsHelper { createProject.userRoleInformation = data.profileInformation; } + createProject.status = UTILS.convertProjectStatus(data.status); + let userProject = await projectQueries.createProject( createProject ); @@ -1936,7 +1944,7 @@ module.exports = class UserProjectsHelper { libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; libraryProjects.data.lastDownloadedAt = new Date(); - libraryProjects.data.status = CONSTANTS.common.NOT_STARTED_STATUS; + libraryProjects.data.status = CONSTANTS.common.STARTED; if (requestedData.startDate) { libraryProjects.data.startDate = requestedData.startDate; @@ -1952,7 +1960,7 @@ module.exports = class UserProjectsHelper { let projectCreation = await database.models.projects.create( _.omit(libraryProjects.data, ["_id"]) ); - + await kafkaProducersHelper.pushProjectToKafka(projectCreation); if (requestedData.rating && requestedData.rating > 0) { @@ -2686,6 +2694,28 @@ function _projectData(data) { }) } +/** + * Check App Version and return status + * @method + * @name _checkAppVersionAndConvertProjectStatus + * @param {String} appVersion - app Version. + * @param {String} status - project status. + * @returns {String} - project status +*/ + +function _checkAppVersionAndConvertProjectStatus( appVersion = "", status ) { + + let convertedStatus; + let appVersionNo = Number(appVersion.split('.',2).join('.')); + + if ( !isNaN(appVersionNo) && appVersionNo < 4.7 ) { + convertedStatus = UTILS.revertProjectStatus(status); + } else { + convertedStatus = UTILS.convertProjectStatus(status); + } + + return convertedStatus; +} From 949ee643887ae97a31b8e8be8cb8fc6813cbfcea Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Tue, 25 Jan 2022 17:19:45 +0530 Subject: [PATCH 068/373] project status changes to reports API's --- controllers/v1/reports.js | 3 +++ controllers/v1/userProjects.js | 3 ++- generics/constants/common.js | 3 ++- generics/helpers/utils.js | 45 +++++++++++++++++++++++++++++++++- module/reports/helper.js | 44 +++++++++++++++++++++++---------- module/userProjects/helper.js | 9 +++++-- 6 files changed, 89 insertions(+), 18 deletions(-) diff --git a/controllers/v1/reports.js b/controllers/v1/reports.js index 71f5f5fc..cb59004b 100644 --- a/controllers/v1/reports.js +++ b/controllers/v1/reports.js @@ -78,6 +78,7 @@ module.exports = class Reports { req.query.reportType, req.query.programId ? req.query.programId : "", req.query.requestPdf ? (req.query.requestPdf).toLowerCase() =="true" ? true :false : false, + req.headers['x-app-ver'] ); return resolve({ @@ -95,6 +96,8 @@ module.exports = class Reports { }) } + + /** * @api {post} /improvement-project/api/v1/reports/getProgramsByEntity/:_id * Get programs by entity. diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 1c2bbf23..2c390f9c 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -644,7 +644,8 @@ module.exports = class UserProjects extends Abstract { let report = await userProjectsHelper.share( req.params._id, taskIds, - req.userDetails.userToken + req.userDetails.userToken, + req.headers['x-app-ver'] ); return resolve({ diff --git a/generics/constants/common.js b/generics/constants/common.js index fdd10b15..499705e5 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -21,6 +21,8 @@ module.exports = { "COMPLETED_STATUS" : "completed", "INPROGRESS_STATUS" : "inProgress", "NOT_STARTED_STATUS" : "notStarted", + "STARTED":"started", + "SUBMITTED_STATUS":"submitted", "OBSERVATION" : "observation", "PUBLISHED_STATUS" : "published", "LEAD_ASSESSOR" : "LEAD_ASSESSOR", @@ -38,7 +40,6 @@ module.exports = { "CRITERIA_LEVEL_REPORT" : "criteriaLevelReport", "LINK" : "link", "DEFAULT_SUBMISSION_REQUIRED" : 1, - "STARTED" : "started", "TASK_SEQUENCE" : "taskSequence", "CHILDREN" : "children", diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 95af57e0..7d54c818 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -170,6 +170,47 @@ function epochTime() { return currentDate; } +/** + * Revert Project Status For Older App + * @function + * @name revertProjectStatus + * @returns {String} returns reverted project status + */ + + function revertProjectStatus(status) { + + let revertedStatus; + + if ( status == CONSTANTS.common.STARTED ) { + revertedStatus = CONSTANTS.common.NOT_STARTED_STATUS; + } else if ( status == CONSTANTS.common.SUBMITTED_STATUS ) { + revertedStatus = CONSTANTS.common.COMPLETED_STATUS; + } else { + revertedStatus = status; + } + + return revertedStatus; +} + +/** + * revert status or not + * @method + * @name revertStatusorNot + * @param {String} appVersion - app Version. + * @returns {Boolean} - true or false +*/ + +function revertStatusorNot( appVersion) { + + let appVersionNo = Number(appVersion.split('.',2).join('.')); + + if ( !isNaN(appVersionNo) && appVersionNo < 4.7 ) { + return true + } else { + return false + } + +} module.exports = { camelCaseToTitleCase : camelCaseToTitleCase, lowerCase : lowerCase, @@ -179,5 +220,7 @@ module.exports = { convertStringToBoolean : convertStringToBoolean, getAllBooleanDataFromModels : getAllBooleanDataFromModels, epochTime : epochTime, - isValidMongoId : isValidMongoId + isValidMongoId : isValidMongoId, + revertProjectStatus:revertProjectStatus, + revertStatusorNot:revertStatusorNot }; diff --git a/module/reports/helper.js b/module/reports/helper.js index 5c428ded..e49a5793 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -34,7 +34,7 @@ module.exports = class ReportsHelper { * @param {Boolean} getPdf - pdf true or false * @returns {Object} Entity report. */ - static entity(entityId = "", userId, userToken, userName, reportType, programId = "", getPdf) { + static entity(entityId = "", userId, userToken, userName, reportType, programId = "", getPdf,appVersion) { return new Promise(async (resolve, reject) => { try { @@ -88,9 +88,9 @@ module.exports = class ReportsHelper { "total": 0, "overdue": 0, }; - projectReport[CONSTANTS.common.COMPLETED_STATUS] = 0; + projectReport[CONSTANTS.common.SUBMITTED_STATUS] = 0; projectReport[CONSTANTS.common.INPROGRESS_STATUS] = 0; - projectReport[CONSTANTS.common.NOT_STARTED_STATUS] = 0; + projectReport[CONSTANTS.common.STARTED] = 0; let types = await this.types(); @@ -100,8 +100,12 @@ module.exports = class ReportsHelper { } }); + + + if (!projectDetails.length > 0) { + if (getPdf == true) { let reportTaskData = {}; @@ -123,7 +127,7 @@ module.exports = class ReportsHelper { projects: projectReport, } - + let response = await reportService.entityReport(userToken, pdfRequest); if (response && response.success == true) { @@ -146,6 +150,8 @@ module.exports = class ReportsHelper { } } else { + + return resolve({ message: CONSTANTS.apiResponses.REPORTS_DATA_NOT_FOUND, data: { @@ -185,9 +191,10 @@ module.exports = class ReportsHelper { let todayDate = moment(project.endDate, "DD.MM.YYYY"); let endDate = moment().format(); - if (project.status == CONSTANTS.common.COMPLETED_STATUS) { - projectReport[CONSTANTS.common.COMPLETED_STATUS] = projectReport[CONSTANTS.common.COMPLETED_STATUS] + 1; + if (project.status == CONSTANTS.common.SUBMITTED_STATUS) { + + projectReport[CONSTANTS.common.SUBMITTED_STATUS] = projectReport[CONSTANTS.common.SUBMITTED_STATUS] + 1; } else if (project.status == CONSTANTS.common.INPROGRESS_STATUS) { @@ -197,17 +204,17 @@ module.exports = class ReportsHelper { projectReport[CONSTANTS.common.INPROGRESS_STATUS] = projectReport[CONSTANTS.common.INPROGRESS_STATUS] + 1; } - } else if (project.status == CONSTANTS.common.NOT_STARTED_STATUS) { + } else if (project.status == CONSTANTS.common.STARTED) { if (todayDate.diff(endDate, 'days') < 1) { projectReport['overdue'] = projectReport['overdue'] + 1; } else { - projectReport[CONSTANTS.common.NOT_STARTED_STATUS] = projectReport[CONSTANTS.common.NOT_STARTED_STATUS] + 1; + projectReport[CONSTANTS.common.STARTED] = projectReport[CONSTANTS.common.STARTED] + 1; } } - projectReport["total"] = projectReport[CONSTANTS.common.NOT_STARTED_STATUS] + + projectReport["total"] = projectReport[CONSTANTS.common.STARTED] + projectReport['overdue'] + projectReport[CONSTANTS.common.INPROGRESS_STATUS] + - projectReport[CONSTANTS.common.COMPLETED_STATUS]; + projectReport[CONSTANTS.common.SUBMITTED_STATUS]; if (project.taskReport) { let keys = Object.keys(project.taskReport); @@ -236,8 +243,16 @@ module.exports = class ReportsHelper { })); - if (getPdf == true) { + if (UTILS.revertStatusorNot(appVersion)) { + + projectReport[CONSTANTS.common.COMPLETED_STATUS] = projectReport[CONSTANTS.common.SUBMITTED_STATUS]; + projectReport[CONSTANTS.common.NOT_STARTED_STATUS] = projectReport[CONSTANTS.common.STARTED]; + delete projectReport[CONSTANTS.common.SUBMITTED_STATUS]; + delete projectReport[CONSTANTS.common.STARTED]; + } + if (getPdf == true) { + let reportTaskData = {}; Object.keys(tasksReport).map(taskData => { reportTaskData[UTILS.camelCaseToTitleCase(taskData)] = tasksReport[taskData]; @@ -269,6 +284,7 @@ module.exports = class ReportsHelper { if (entityId != "") { pdfRequest['entityName'] = projectDetails[0].entityInformation.name; } + let response = await reportService.entityReport(userToken, pdfRequest); if (response && response.success == true) { @@ -312,6 +328,7 @@ module.exports = class ReportsHelper { } + /** * Get programs list. * @method @@ -595,9 +612,9 @@ module.exports = class ReportsHelper { } let color = ""; - if (status == CONSTANTS.common.NOT_STARTED_STATUS) { + if (status == CONSTANTS.common.STARTED) { color = "#f5f5f5"; - } else if (status == CONSTANTS.common.COMPLETED_STATUS) { + } else if (status == CONSTANTS.common.SUBMITTED_STATUS ) { color = "#20ba8d"; } else if (status == CONSTANTS.common.INPROGRESS_STATUS) { color = "#ef8c2b"; @@ -635,6 +652,7 @@ module.exports = class ReportsHelper { } }); } + } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4aca33dc..8cd0a0e8 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1473,7 +1473,7 @@ module.exports = class UserProjectsHelper { * @returns {Object} Downloadable pdf url. */ - static share(projectId = "", taskIds = [], userToken) { + static share(projectId = "", taskIds = [], userToken,appVersion) { return new Promise(async (resolve, reject) => { try { @@ -1563,7 +1563,12 @@ module.exports = class UserProjectsHelper { delete projectDocument.categories; delete projectDocument.metaInformation; delete projectDocument.programInformation; - + + + if (UTILS.revertStatusorNot(appVersion)) { + projectDocument.status = UTILS.revertProjectStatus(projectDocument.status); + } + let response = await reportService.projectAndTaskReport(userToken, projectDocument, projectPdf); if (response && response.success == true) { From f56ed7b03da651bcdf75b3f36ce54d7676b3d9a5 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 25 Jan 2022 17:42:17 +0530 Subject: [PATCH 069/373] add data to result --- module/project/templates/helper.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index b5fa0b9d..e29e4bb5 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -987,7 +987,6 @@ module.exports = class ProjectTemplatesHelper { "name", "programId", "programName", - "externalId", "projectTemplateId", "link" ] @@ -1049,7 +1048,6 @@ module.exports = class ProjectTemplatesHelper { templateData[0].tasks = await this.tasksAndSubTasks(templateData[0]._id); } - let result = await _templateInformation(templateData[0]) if( !result.success ) { return resolve(result); @@ -1068,7 +1066,17 @@ module.exports = class ProjectTemplatesHelper { templateData[0].projectId = project[0]._id; } } - result.data=solutionsResult; + if( !result.data.programInformation ){ + result.data.programInformation = { + programId : solutionsResult.programId, + programName : solutionsResult.programName + } + } + result.data.solutionInformation = { + _id : solutionsResult._id, + name : solutionsResult.name, + link : solutionsResult.link + } return resolve({ success : false, data : result.data, @@ -1267,7 +1275,6 @@ function _templateInformation(project) { project[projectMetaKey] = project.metaInformation[projectMetaKey]; }); } - delete project.metaInformation; delete project.__v; From 0a4277083e16dc5523939ac190cbc8e4ead3816f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 27 Jan 2022 11:54:09 +0530 Subject: [PATCH 070/373] solution model added --- controllers/v1/solutions.js | 9 ++- databaseQueries/solutions.js | 62 ++++++++++++++++++ generics/services/core.js | 65 +----------------- models/solutions.js | 102 +++++++++++++++++++++++++++++ module/project/templates/helper.js | 13 ++-- 5 files changed, 179 insertions(+), 72 deletions(-) create mode 100644 databaseQueries/solutions.js create mode 100644 models/solutions.js diff --git a/controllers/v1/solutions.js b/controllers/v1/solutions.js index 1254b978..186a0e1e 100644 --- a/controllers/v1/solutions.js +++ b/controllers/v1/solutions.js @@ -7,7 +7,14 @@ // Dependencies const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); -module.exports = class Solutions { +module.exports = class Solutions extends Abstract{ + constructor() { + super("solutions"); + } + + static get name() { + return "solutions"; + } /** * @api {post} /improvement-project/api/v1/solutions/create Create solution diff --git a/databaseQueries/solutions.js b/databaseQueries/solutions.js new file mode 100644 index 00000000..c4cc635e --- /dev/null +++ b/databaseQueries/solutions.js @@ -0,0 +1,62 @@ +/** + * name : solutions.js + * author : Vishnu + * created-date : 26-Jan-2022 + * Description : solutions helper for DB interactions. + */ + +// Dependencies + +/** + * Solutions + * @class +*/ + + + +module.exports= class Solutions{ + /** + * Solution details. + * @method + * @name solutionsDocument + * @param {Array} [filterData = "all"] - solutions filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} solutions details. + */ + + static solutionsDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + let solutionsDoc = + await database.models.solutions.find( + queryObject, + projection + ).lean(); + + return resolve(solutionsDoc); + + } catch (error) { + return reject(error); + } + }); + } +} \ No newline at end of file diff --git a/generics/services/core.js b/generics/services/core.js index 5da4fb66..4e8ca33b 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -721,68 +721,6 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution }) } -/** - * List of solutions. - * @function - * @name solutionsDocument - * @param {Object} filterData - Filter data. - * @param {Array} projection - Projected data. - * @param {Array} skipFields - Field to skip. - * @returns {JSON} - List of solutions. -*/ - -const solutionsDocuments = function ( - filterData = "all", - projection = "all", - skipFields = "none" -) { - return new Promise(async (resolve, reject) => { - try { - - const url = ML_CORE_URL + CONSTANTS.endpoints.GET_LIST_SOLUTION; - - const options = { - headers : { - "content-type": "application/json", - "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, - }, - json : { - query : filterData, - projection : projection, - skipFields : skipFields - } - }; - - request.post(url,options,kendraCallback); - - function kendraCallback(err, data) { - - let result = { - success : true - }; - - if (err) { - result.success = false; - } else { - - let response = data.body; - - if( response.status === HTTP_STATUS_CODE['ok'].status ) { - result["data"] = response.result; - } else { - result.success = false; - } - } - - return resolve(result); - } - - } catch (error) { - return reject(error); - } - }) -} - module.exports = { entityTypesDocuments : entityTypesDocuments, rolesDocuments : rolesDocuments, @@ -796,7 +734,6 @@ module.exports = { createSolution: createSolution, solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, - getDownloadableUrl : getDownloadableUrl, - solutionsDocuments : solutionsDocuments + getDownloadableUrl : getDownloadableUrl }; diff --git a/models/solutions.js b/models/solutions.js new file mode 100644 index 00000000..511c5d4f --- /dev/null +++ b/models/solutions.js @@ -0,0 +1,102 @@ +/** + * name : solutions-model.js. + * author : Vishnu. + * created-date : 26-jan-2022. + * Description : Schema for solutions. + */ +module.exports = { + name: "solutions", + schema: { + externalId: String, + isReusable: Boolean, + name: String, + description: String, + author: String, + parentSolutionId: "ObjectId", + resourceType: Array, + language: Array, + keywords: Array, + concepts: Array, + scoringSystem: String, + levelToScoreMapping: Object, + themes: Array, + flattenedThemes : Array, + questionSequenceByEcm: Object, + entityTypeId: "ObjectId", + entityType: String, + type: String, + subType: String, + entities: Array, + programId: "ObjectId", + programExternalId: String, + programName: String, + programDescription: String, + entityProfileFieldsPerEntityTypes: Object, + startDate: Date, + endDate: { + type : Date, + index : true + }, + status: String, + evidenceMethods: Object, + sections: Object, + registry: Array, + frameworkId: "ObjectId", + frameworkExternalId: String, + parentSolutionId: "ObjectId", + noOfRatingLevels: Number, + isRubricDriven: { type : Boolean, default: false }, + enableQuestionReadOut: { type : Boolean, default: false }, + isReusable: Boolean, + roles: Object, + observationMetaFormKey: String, + updatedBy: String, + captureGpsLocationAtQuestionLevel:{ type : Boolean, default: false }, + sendSubmissionRatingEmailsTo: String, + creator: String, + linkTitle: String, + linkUrl: String, + isAPrivateProgram : { + default : false, + type : Boolean + }, + assessmentMetaFormKey : String, + allowMultipleAssessemts : { + default : false, + type : Boolean + }, + isDeleted: { + default : false, + type : Boolean, + index : true + }, + project : Object, + referenceFrom : String, + scope : { + entityType : String, + entityTypeId : "ObjectId", + entities : { + type : Array, + index : true + }, + roles : [{ + _id : "ObjectId", + code : { + type : String, + index : true + } + }] + }, + pageHeading: { + default : "Domains", + type : String + }, + criteriaLevelReport : Boolean, + license:Object, + link: String, + minNoOfSubmissionsRequired: { + type: Number, + default: 1 + } + } + }; \ No newline at end of file diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index e29e4bb5..9b733b59 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -21,6 +21,7 @@ const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates") const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); +const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); module.exports = class ProjectTemplatesHelper { @@ -972,6 +973,8 @@ module.exports = class ProjectTemplatesHelper { message:CONSTANTS.apiResponses.TEMPLATE_ID_OR_LINK_REQUIRED } } + + let findQuery = {}; //get data when link is given if( link ){ @@ -979,9 +982,7 @@ module.exports = class ProjectTemplatesHelper { let queryData = {}; queryData["link"] =link; - let solutionDocument = - await coreService.solutionsDocuments( - queryData, + let solutionDocument = await solutionsQueries.solutionsDocument(queryData, [ "_id", "name", @@ -991,15 +992,13 @@ module.exports = class ProjectTemplatesHelper { "link" ] ); - - if( !solutionDocument.success || solutionDocument.data.length === 0 ) { + if( !solutionDocument.length > 0 ) { throw { message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, status : HTTP_STATUS_CODE['bad_request'].status } } - - let solutiondata = solutionDocument.data; + let solutiondata = solutionDocument; templateId = solutiondata[0].projectTemplateId; if( !templateId ){ return resolve({ From 3659b149a0e5e4583e4a08db4d28b256fae77e8b Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 27 Jan 2022 14:12:45 +0530 Subject: [PATCH 071/373] project status check added --- generics/constants/api-responses.js | 3 ++- module/userProjects/helper.js | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index fb5d0ed4..e7113016 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -122,5 +122,6 @@ module.exports = { "PROJECT_TEMPLATE_UPDATED" : "Successfully updated project template", "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", "TEMPLATE_ID_OR_LINK_REQUIRED" : "TemplateId or Link either one is required", - "TEMPLATE_ID_NOT_FOUND_IN_SOLUTION" : "Could not found templateId in solution" + "TEMPLATE_ID_NOT_FOUND_IN_SOLUTION" : "Could not found templateId in solution", + "FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED" : "Failed to sync, Project is already Submitted" }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4aca33dc..e835bdb9 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -111,7 +111,8 @@ module.exports = class UserProjectsHelper { "solutionInformation.externalId", "entityInformation._id", "lastDownloadedAt", - "appInformation" + "appInformation", + "status" ]); if (!userProject.length > 0) { @@ -129,6 +130,13 @@ module.exports = class UserProjectsHelper { }; } + if ( userProject[0].status == CONSTANTS.common.SUBMITTED_STATUS ) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED + }; + } + const projectsModel = Object.keys(schemas["projects"].schema); let updateProject = {}; From 71b3bab071237dbac1df24b6b8ba4adff52f3343 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 27 Jan 2022 17:31:18 +0530 Subject: [PATCH 072/373] validation added to controller --- controllers/v1/project/templates.js | 6 ++++++ module/project/templates/helper.js | 8 -------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/controllers/v1/project/templates.js b/controllers/v1/project/templates.js index 9d46f314..486ad6c2 100644 --- a/controllers/v1/project/templates.js +++ b/controllers/v1/project/templates.js @@ -669,6 +669,12 @@ module.exports = class ProjectTemplates extends Abstract { return new Promise(async (resolve, reject) => { try { + if( !req.params._id && !req.query.link ) { + throw{ + status:HTTP_STATUS_CODE.bad_request.status, + message:CONSTANTS.apiResponses.TEMPLATE_ID_OR_LINK_REQUIRED + } + } let projectTemplatesDetails = await projectTemplatesHelper.details( diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 9b733b59..a1b1b58e 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -967,14 +967,6 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { let solutionsResult = {}; - if(templateId == "" && link == ""){ - throw{ - status:HTTP_STATUS_CODE.bad_request.status, - message:CONSTANTS.apiResponses.TEMPLATE_ID_OR_LINK_REQUIRED - } - } - - let findQuery = {}; //get data when link is given if( link ){ From 325f5351bf985198085d162bcc60d431e505d82b Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 27 Jan 2022 19:04:58 +0530 Subject: [PATCH 073/373] added completed date --- models/projects.js | 1 + 1 file changed, 1 insertion(+) diff --git a/models/projects.js b/models/projects.js index 08c98120..96495e2a 100644 --- a/models/projects.js +++ b/models/projects.js @@ -125,5 +125,6 @@ module.exports = { type : Array, default : [] }, + completedDate: Date } }; From 20a1da61bac5c9f816f1230f5e775f27c9fc3186 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 27 Jan 2022 20:08:41 +0530 Subject: [PATCH 074/373] remove version check from helper --- module/userProjects/helper.js | 38 +++++++++-------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c1d8e908..ec4e3209 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -11,6 +11,7 @@ const coreService = require(GENERICS_FILES_PATH + "/services/core"); const libraryCategoriesHelper = require(MODULES_BASE_PATH + "/library/categories/helper"); const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); const projectTemplateTasksHelper = require(MODULES_BASE_PATH + "/project/templateTasks/helper"); +const { util } = require('chai'); const { v4: uuidv4 } = require('uuid'); const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const reportService = require(GENERICS_FILES_PATH + "/services/report"); @@ -1187,12 +1188,14 @@ module.exports = class UserProjectsHelper { userId, userRoleInformation ); - - projectDetails.data.status = _checkAppVersionAndConvertProjectStatus( - appVersion, - projectDetails.data.status - ); - + + let revertStatusorNot = UTILS.revertStatusorNot(appVersion); + if ( revertStatusorNot ) { + projectDetails.data.status = UTILS.revertProjectStatus(projectDetails.data.status); + } else { + projectDetails.data.status = UTILS.convertProjectStatus(projectDetails.data.status); + } + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, @@ -2707,28 +2710,5 @@ function _projectData(data) { }) } -/** - * Check App Version and return status - * @method - * @name _checkAppVersionAndConvertProjectStatus - * @param {String} appVersion - app Version. - * @param {String} status - project status. - * @returns {String} - project status -*/ - -function _checkAppVersionAndConvertProjectStatus( appVersion = "", status ) { - - let convertedStatus; - let appVersionNo = Number(appVersion.split('.',2).join('.')); - - if ( !isNaN(appVersionNo) && appVersionNo < 4.7 ) { - convertedStatus = UTILS.revertProjectStatus(status); - } else { - convertedStatus = UTILS.convertProjectStatus(status); - } - - return convertedStatus; -} - From adc0798e16034979c8e285d15ac908557002db70 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 27 Jan 2022 22:02:01 +0530 Subject: [PATCH 075/373] added completed date --- module/userProjects/helper.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index ec4e3209..741187e4 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -11,7 +11,6 @@ const coreService = require(GENERICS_FILES_PATH + "/services/core"); const libraryCategoriesHelper = require(MODULES_BASE_PATH + "/library/categories/helper"); const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); const projectTemplateTasksHelper = require(MODULES_BASE_PATH + "/project/templateTasks/helper"); -const { util } = require('chai'); const { v4: uuidv4 } = require('uuid'); const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const reportService = require(GENERICS_FILES_PATH + "/services/report"); @@ -332,6 +331,10 @@ module.exports = class UserProjectsHelper { } updateProject.status = UTILS.convertProjectStatus(data.status); + + if ( data.status == CONSTANTS.common.COMPLETED_STATUS || data.status == CONSTANTS.common.SUBMITTED_STATUS ) { + updateProject.completedDate = new Date(); + } let projectUpdated = await projectQueries.findOneAndUpdate( From ea67de18565d50009b1f0cbd2aff1b046bf2bd1a Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 28 Jan 2022 02:08:18 +0530 Subject: [PATCH 076/373] task sequence fix --- module/userProjects/helper.js | 40 +++++++++-------------------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 741187e4..cff1fc10 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2072,38 +2072,12 @@ function _projectInformation(project) { project.programId = project.programInformation._id; project.programName = project.programInformation.name; } - //order task based on task sequence - if (project.taskSequence && project.taskSequence.length > 0) { - - let tasks = []; - let taskSequence = project.taskSequence ? project.taskSequence : []; - let projectTasks = project.tasks; - - for (let taskCounter = 0; taskCounter < taskSequence.length; taskCounter++) { - - let eachTask = projectTasks.find(item => item.externalId == taskSequence[taskCounter]); - if (eachTask && Object.keys(eachTask).length > 0) { - - let childTasks = []; - if (eachTask.children && eachTask.children.length > 0) { - - let childTaskSequence = eachTask.taskSequence; - for (let childTaskPointer = 0; childTaskPointer < childTaskSequence.length; childTaskPointer++) { - let eachChildTask = eachTask.children.find(childItem => childItem.externalId == childTaskSequence[childTaskPointer]); - childTasks.push(eachChildTask); - } - - eachTask.children = childTasks; - } - - tasks.push(eachTask); - } - } - - project.tasks = tasks; - } if (project.tasks && project.tasks.length > 0) { + //order task based on task sequence + if ( project.taskSequence && project.taskSequence.length > 0 ) { + project.tasks = taskArrayBySequence(project.tasks, project.taskSequence, 'externalId'); + } let attachments = []; let mapTaskIdToAttachment = {}; @@ -2201,6 +2175,12 @@ function _projectInformation(project) { }) } +function taskArrayBySequence (taskArray, sequenceArray, key) { + var map = sequenceArray.reduce((acc, value, index) => (acc[value] = index + 1, acc), {}) + const sortedTaskArray = taskArray.sort((a, b) => (map[a[key]] || Infinity) - (map[b[key]] || Infinity)) + return sortedTaskArray +}; + /** * Task of project. * @method From dd71e0be4eb61bb285be1172e7f8c34a0a459d91 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 31 Jan 2022 00:21:55 +0530 Subject: [PATCH 077/373] recommended for added in project model --- models/projects.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/models/projects.js b/models/projects.js index 96495e2a..bfca077a 100644 --- a/models/projects.js +++ b/models/projects.js @@ -125,6 +125,10 @@ module.exports = { type : Array, default : [] }, - completedDate: Date + completedDate: Date, + recommendedFor : { + type : Array, + default : [] + } } }; From c0db507e5421b6b964e40ec0df2b6983061a1248 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Wed, 2 Feb 2022 14:52:13 +0530 Subject: [PATCH 078/373] config/kafka.js --- config/kafka.js | 4 ++++ generics/kafka/producers.js | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/config/kafka.js b/config/kafka.js index 34b7a90f..50a80c27 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -73,6 +73,10 @@ var _sendToKafkaConsumers = function (topic,host) { consumer.on('message', async function (message) { + console.log("-------Kafka log starts here------------------"); + console.log("Message: ", JSON.stringify(message)); + console.log("-------Kafka log ends here------------------"); + if (message && message.topic === SUBMISSION_TOPIC) { submissionsConsumer.messageReceived(message); diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index b32404aa..b9d70eb7 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -49,6 +49,11 @@ const pushMessageToKafka = function(payload) { throw reject("Kafka configuration is not done"); } + console.log("-------Kafka log starts here------------------"); + console.log("Message: ", JSON.stringify(payload)); + console.log("-------Kafka log ends here------------------"); + + kafkaClient.kafkaProducer.send(payload, (err, data) => { if (err) { return reject("Kafka push to topic "+ payload[0].topic +" failed."); From 406ae8b5a9d36698bed2b01ebe30bc75c41f3f6f Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Wed, 2 Feb 2022 16:11:11 +0530 Subject: [PATCH 079/373] topic name added to kafka logs --- config/kafka.js | 1 + generics/kafka/producers.js | 1 + 2 files changed, 2 insertions(+) diff --git a/config/kafka.js b/config/kafka.js index 50a80c27..e0754ecb 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -74,6 +74,7 @@ var _sendToKafkaConsumers = function (topic,host) { consumer.on('message', async function (message) { console.log("-------Kafka log starts here------------------"); + console.log("Topic Name: ", topic); console.log("Message: ", JSON.stringify(message)); console.log("-------Kafka log ends here------------------"); diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index b9d70eb7..ec643c71 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -50,6 +50,7 @@ const pushMessageToKafka = function(payload) { } console.log("-------Kafka log starts here------------------"); + console.log("Topic Name: ", payload[0].topic); console.log("Message: ", JSON.stringify(payload)); console.log("-------Kafka log ends here------------------"); From 5c2a1138b5822bd7bc3c70b6741665785f7c65ae Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 3 Feb 2022 17:07:05 +0530 Subject: [PATCH 080/373] Authenticator condition updated --- generics/middleware/authenticator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index 031b42ac..b3599204 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -56,7 +56,7 @@ module.exports = async function (req, res, next, token = "") { } })); - if(guestAccess==true) { + if( guestAccess == true && !token ) { next(); return; } From e9f0b781807e460f593bacf5482fe1aeff523629 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Mon, 7 Feb 2022 11:38:31 +0530 Subject: [PATCH 081/373] kafka logs changes: --- config/kafka.js | 4 ++-- generics/kafka/producers.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/kafka.js b/config/kafka.js index e0754ecb..3d248170 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -73,10 +73,10 @@ var _sendToKafkaConsumers = function (topic,host) { consumer.on('message', async function (message) { - console.log("-------Kafka log starts here------------------"); + console.log("-------Kafka consumer log starts here------------------"); console.log("Topic Name: ", topic); console.log("Message: ", JSON.stringify(message)); - console.log("-------Kafka log ends here------------------"); + console.log("-------Kafka consumer log ends here------------------"); if (message && message.topic === SUBMISSION_TOPIC) { diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index ec643c71..5437f5bf 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -49,10 +49,10 @@ const pushMessageToKafka = function(payload) { throw reject("Kafka configuration is not done"); } - console.log("-------Kafka log starts here------------------"); + console.log("-------Kafka producer log starts here------------------"); console.log("Topic Name: ", payload[0].topic); console.log("Message: ", JSON.stringify(payload)); - console.log("-------Kafka log ends here------------------"); + console.log("-------Kafka producer log ends here------------------"); kafkaClient.kafkaProducer.send(payload, (err, data) => { From a89019b8c07ea9038f101e0dd08faf5934b7ce0f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 7 Feb 2022 13:24:25 +0530 Subject: [PATCH 082/373] externalid && _id check conflict solved --- module/project/templates/helper.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index a1b1b58e..9ef56eee 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -984,6 +984,7 @@ module.exports = class ProjectTemplatesHelper { "link" ] ); + if( !solutionDocument.length > 0 ) { throw { message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, @@ -1000,17 +1001,20 @@ module.exports = class ProjectTemplatesHelper { }); } solutionsResult = solutiondata; + templateId=templateId.toString(); } if( templateId ){ - let validateTemplateId = UTILS.isValidMongoId(templateId); + let validateTemplateId =await UTILS.isValidMongoId(templateId); + if( validateTemplateId ) { findQuery["_id"] = templateId; } else { findQuery["externalId"] = templateId; } - } + } + //getting template data using templateId let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", From 9b97aad7717ea148f48deeadc5d2f0ce1eb03314 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 7 Feb 2022 13:56:52 +0530 Subject: [PATCH 083/373] removed- await --- module/project/templates/helper.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 9ef56eee..fad53f38 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1005,8 +1005,7 @@ module.exports = class ProjectTemplatesHelper { } if( templateId ){ - let validateTemplateId =await UTILS.isValidMongoId(templateId); - + let validateTemplateId = UTILS.isValidMongoId(templateId); if( validateTemplateId ) { findQuery["_id"] = templateId; } else { @@ -1014,7 +1013,6 @@ module.exports = class ProjectTemplatesHelper { } } - //getting template data using templateId let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", From 11380033d269c3a07747132c26de4e23560f0a62 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Tue, 8 Feb 2022 16:06:39 +0530 Subject: [PATCH 084/373] kafka logs changes --- config/kafka.js | 4 ++-- generics/kafka/producers.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/kafka.js b/config/kafka.js index e0754ecb..39a9c925 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -73,10 +73,10 @@ var _sendToKafkaConsumers = function (topic,host) { consumer.on('message', async function (message) { - console.log("-------Kafka log starts here------------------"); + console.log("-------Kafka conumer log starts here------------------"); console.log("Topic Name: ", topic); console.log("Message: ", JSON.stringify(message)); - console.log("-------Kafka log ends here------------------"); + console.log("-------Kafka conumer log ends here------------------"); if (message && message.topic === SUBMISSION_TOPIC) { diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index ec643c71..5437f5bf 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -49,10 +49,10 @@ const pushMessageToKafka = function(payload) { throw reject("Kafka configuration is not done"); } - console.log("-------Kafka log starts here------------------"); + console.log("-------Kafka producer log starts here------------------"); console.log("Topic Name: ", payload[0].topic); console.log("Message: ", JSON.stringify(payload)); - console.log("-------Kafka log ends here------------------"); + console.log("-------Kafka producer log ends here------------------"); kafkaClient.kafkaProducer.send(payload, (err, data) => { From 943893ca8490e78908fd2e714cee6e2b2223bec9 Mon Sep 17 00:00:00 2001 From: rakeshSgr Date: Tue, 8 Feb 2022 16:53:37 +0530 Subject: [PATCH 085/373] kafka log change --- config/kafka.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/kafka.js b/config/kafka.js index 39a9c925..3d248170 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -73,10 +73,10 @@ var _sendToKafkaConsumers = function (topic,host) { consumer.on('message', async function (message) { - console.log("-------Kafka conumer log starts here------------------"); + console.log("-------Kafka consumer log starts here------------------"); console.log("Topic Name: ", topic); console.log("Message: ", JSON.stringify(message)); - console.log("-------Kafka conumer log ends here------------------"); + console.log("-------Kafka consumer log ends here------------------"); if (message && message.topic === SUBMISSION_TOPIC) { From 0d8e6ec4398cec3837faaf07dd2a497e794fd908 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 8 Feb 2022 18:21:40 +0530 Subject: [PATCH 086/373] task issue fix --- module/project/templates/helper.js | 127 ++++++++++++++++------------- 1 file changed, 69 insertions(+), 58 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index fad53f38..5e2f61cd 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -811,80 +811,92 @@ module.exports = class ProjectTemplatesHelper { return new Promise(async (resolve, reject) => { try { - let newProjectTemplateTask, duplicateTemplateTask,newProjectTemplateChildTask,duplicateChildTemplateTask; let newTaskId = []; - await Promise.all(taskIds.map(async taskId => { - + for ( let pointerToTask = 0; pointerToTask < taskIds.length; pointerToTask++ ) { + + let taskId = taskIds[pointerToTask]; let taskData = await projectTemplateTaskQueries.taskDocuments( { - _id : taskId + _id : taskId, + parentId : { $exists : false } }); - if(taskData && taskData.length > 0){ + if( taskData && taskData.length > 0 ) { taskData = taskData[0]; } - if(taskData){ - //duplicate task - newProjectTemplateTask = {...taskData}; - newProjectTemplateTask.projectTemplateId = duplicateTemplateId; - newProjectTemplateTask.projectTemplateExternalId = duplicateTemplateExternalId; - newProjectTemplateTask.externalId = taskData.externalId +"-"+ UTILS.epochTime(); - duplicateTemplateTask = - await projectTemplateTaskQueries.createTemplateTask( - _.omit(newProjectTemplateTask, ["_id"]) - ); - newTaskId.push(duplicateTemplateTask._id); - //duplicate child task - if(duplicateTemplateTask.children && duplicateTemplateTask.children.length > 0){ - let childTaskIdArray = []; - let childTaskIds = duplicateTemplateTask.children; - - if(childTaskIds && childTaskIds.length > 0){ - await Promise.all(childTaskIds.map(async childtaskId => { - let childTaskData = await projectTemplateTaskQueries.taskDocuments( - { - _id : childtaskId - }); - - if(childTaskData && childTaskData.length > 0){ - childTaskData = childTaskData[0]; - } - - if(childTaskData){ - newProjectTemplateChildTask = {...childTaskData}; - newProjectTemplateChildTask.projectTemplateId = duplicateTemplateId; - newProjectTemplateChildTask.projectTemplateExternalId = duplicateTemplateExternalId; - newProjectTemplateChildTask.parentId = duplicateTemplateTask._id; - newProjectTemplateChildTask.externalId = childTaskData.externalId +"-"+ UTILS.epochTime(); - duplicateChildTemplateTask = - await projectTemplateTaskQueries.createTemplateTask( - _.omit(newProjectTemplateChildTask, ["_id"]) - ); - - childTaskIdArray.push(duplicateChildTemplateTask._id); - } - })) + if ( taskData && Object.keys(taskData).length > 0 ) { - if(childTaskIdArray && childTaskIdArray.length > 0){ - let updateTaskData = projectTemplateTaskQueries.updateTaskDocument( - { - _id : duplicateTemplateTask._id - }, + //duplicate parent task + let newProjectTemplateTask = {...taskData}; + newProjectTemplateTask.projectTemplateId = duplicateTemplateId; + newProjectTemplateTask.projectTemplateExternalId = duplicateTemplateExternalId; + newProjectTemplateTask.externalId = taskData.externalId +"-"+ UTILS.epochTime(); + + let duplicateTemplateTask = + await database.models.projectTemplateTasks.create( + _.omit(newProjectTemplateTask, ["_id"]) + ); + + newTaskId.push(duplicateTemplateTask._id); + + //duplicate child task + if ( duplicateTemplateTask.children && duplicateTemplateTask.children.length > 0 ) { + + let childTaskIdArray = []; + let childTaskIds = duplicateTemplateTask.children; + + if ( childTaskIds && childTaskIds.length > 0 ) { + + for ( let pointerToChild = 0 ; pointerToChild < childTaskIds.length ; pointerToChild++ ) { + + let childtaskId = childTaskIds[pointerToChild]; + let childTaskData = await projectTemplateTaskQueries.taskDocuments( { - $set : { - children : childTaskIdArray - } - }) + _id : childtaskId + }); + + if ( childTaskData && childTaskData.length > 0 ) { + childTaskData = childTaskData[0]; + } + + if ( childTaskData && Object.keys(childTaskData).length > 0 ) { + + let newProjectTemplateChildTask = {...childTaskData}; + newProjectTemplateChildTask.projectTemplateId = duplicateTemplateId; + newProjectTemplateChildTask.projectTemplateExternalId = duplicateTemplateExternalId; + newProjectTemplateChildTask.parentId = duplicateTemplateTask._id; + newProjectTemplateChildTask.externalId = childTaskData.externalId +"-"+ UTILS.epochTime(); + + let duplicateChildTemplateTask = + await database.models.projectTemplateTasks.create( + _.omit(newProjectTemplateChildTask, ["_id"]) + ); + + childTaskIdArray.push(duplicateChildTemplateTask._id); + newTaskId.push(duplicateChildTemplateTask._id); } } + //update new subtask ids to parent task + if(childTaskIdArray && childTaskIdArray.length > 0){ + let updateTaskData = await projectTemplateTaskQueries.updateTaskDocument( + { + _id : duplicateTemplateTask._id + }, + { + $set : { + children : childTaskIdArray + } + }) + } } } - })) + } + } let updateDuplicateTemplate; - + //adding duplicate tasj to duplicate template if(newTaskId && newTaskId.length > 0){ updateDuplicateTemplate = await projectTemplateQueries.findOneAndUpdate( @@ -902,7 +914,6 @@ module.exports = class ProjectTemplatesHelper { updateDuplicateTemplate ); - } catch (error) { return reject(error); } From 5c4eb4ccc843f2316aaee457c18bc5d5c177ca52 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 15 Feb 2022 10:40:50 +0530 Subject: [PATCH 087/373] fix constants --- module/project/templateTasks/helper.js | 2 +- module/project/templates/helper.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 5298b12d..082b4777 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -815,7 +815,7 @@ module.exports = class ProjectTemplateTasksHelper { if( !taskUpdatedData._id ) { throw { - message : constants.apiResponses.TEMPLATE_TASK_NOT_UPDATED + message : CONSTANTS.apiResponses.TEMPLATE_TASK_NOT_UPDATED } } diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 5e2f61cd..877880b1 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -442,7 +442,7 @@ module.exports = class ProjectTemplatesHelper { if ( !(template.length > 0 && template[0]._id) ) { currentData["UPDATE_STATUS"] = - constants.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; + CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; } else { let templateData = await this.templateData( @@ -468,7 +468,7 @@ module.exports = class ProjectTemplatesHelper { if( !projectTemplateUpdated || !projectTemplateUpdated._id ) { currentData["UPDATE_STATUS"] = - constants.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED; + CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED; } // Add projects count to categories @@ -1199,7 +1199,7 @@ module.exports = class ProjectTemplatesHelper { if( !templateUpdatedData._id ) { throw { - message : constants.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED } } From 894cd810ec4e83d5273307ecea18274a2c01756f Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 18 Feb 2022 01:54:27 +0530 Subject: [PATCH 088/373] project and task attachments --- generics/constants/common.js | 3 +-- models/projects.js | 7 ++++++- module/userProjects/helper.js | 31 ++++++++++++++++++++++++------- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index 499705e5..52c7fd75 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -42,6 +42,5 @@ module.exports = { "DEFAULT_SUBMISSION_REQUIRED" : 1, "TASK_SEQUENCE" : "taskSequence", "CHILDREN" : "children", - - + "ATTACHMENT_TYPE_LINK" : "link" }; diff --git a/models/projects.js b/models/projects.js index bfca077a..597b8d2d 100644 --- a/models/projects.js +++ b/models/projects.js @@ -129,6 +129,11 @@ module.exports = { recommendedFor : { type : Array, default : [] - } + }, + attachments : { + type : Array, + default : [] + }, + remarks : String } }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 8dbaca11..c84fb54b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -530,12 +530,11 @@ module.exports = class UserProjectsHelper { } let result = await _projectInformation(projectDetails[0]); - + if (!result.success) { return resolve(result); } - console.log("Project information is",result); return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, @@ -2082,6 +2081,7 @@ function _projectInformation(project) { let attachments = []; let mapTaskIdToAttachment = {}; + let mapLinkAttachment = {}; for (let task = 0; task < project.tasks.length; task++) { @@ -2094,13 +2094,21 @@ function _projectInformation(project) { attachment++ ) { let currentAttachment = currentTask.attachments[attachment]; - attachments.push(currentAttachment.sourcePath); - if (!mapTaskIdToAttachment[currentAttachment.sourcePath]) { + //remove link attachment from attachments + if (currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { + if (!Array.isArray(mapLinkAttachment[currentTask._id]) || !mapLinkAttachment[currentTask._id].length ) { + mapLinkAttachment[currentTask._id] = []; + } + mapLinkAttachment[currentTask._id].push(currentAttachment); + } else { + attachments.push(currentAttachment.sourcePath); + } + + if (!mapTaskIdToAttachment[currentAttachment.sourcePath] && currentAttachment.type != CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { mapTaskIdToAttachment[currentAttachment.sourcePath] = { taskId: currentTask._id }; - } } } @@ -2142,6 +2150,17 @@ function _projectInformation(project) { } + //add link attachment to attachments + if ( mapLinkAttachment && Object.keys(mapLinkAttachment).length > 0 ) { + + Object.keys(mapLinkAttachment).forEach(eachTaskId => { + + let taskIdIndex = project.tasks.findIndex(task => task._id === eachTaskId); + if ( taskIdIndex > -1 ) { + project.tasks[taskIdIndex].attachments.concat(mapLinkAttachment[eachTaskId]); + } + }) + } } project.status = @@ -2159,8 +2178,6 @@ function _projectInformation(project) { delete project.solutionInformation; delete project.programInformation; - console.log("project data is",project); - return resolve({ success: true, data: project From e02e35a6ad20cb0b30622964d6b977fb14f46e76 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 18 Feb 2022 18:48:13 +0530 Subject: [PATCH 089/373] project attachment --- module/userProjects/helper.js | 57 +++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c84fb54b..44a3cc23 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2095,7 +2095,7 @@ function _projectInformation(project) { ) { let currentAttachment = currentTask.attachments[attachment]; - //remove link attachment from attachments + //remove link attachment from task attachments if (currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { if (!Array.isArray(mapLinkAttachment[currentTask._id]) || !mapLinkAttachment[currentTask._id].length ) { mapLinkAttachment[currentTask._id] = []; @@ -2150,7 +2150,7 @@ function _projectInformation(project) { } - //add link attachment to attachments + //add link attachment to task attachments if ( mapLinkAttachment && Object.keys(mapLinkAttachment).length > 0 ) { Object.keys(mapLinkAttachment).forEach(eachTaskId => { @@ -2163,6 +2163,59 @@ function _projectInformation(project) { } } + //project attachments + if ( project.attachments && project.attachments.length > 0 ) { + + let projectLinkAttachments = []; + let projectAttachments = []; + + for ( + let pointerToAttachment = 0; + pointerToAttachment < project.attachments.length; + pointerToAttachment++ + ) { + + let currentProjectAttachment = project.attachments[pointerToAttachment]; + if ( currentProjectAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { + projectLinkAttachments.push(currentProjectAttachment); + } else { + projectAttachments.push(currentProjectAttachment.sourcePath); + } + } + + if ( projectAttachments && projectAttachments.length > 0 ) { + + let projectAttachmentsUrl = + await coreService.getDownloadableUrl( + { + filePaths: projectAttachments + } + ); + + if (!projectAttachmentsUrl.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND + } + } + + if (projectAttachmentsUrl.data.length > 0) { + projectAttachmentsUrl.data.forEach(eachAttachment => { + let projectAttachmentIndex = + project.attachments.findIndex(attachmentData => attachmentData.sourcePath == eachAttachment.filePath); + console.log(projectAttachmentIndex,"projectAttachmentIndex") + if (projectAttachmentIndex > -1) { + project.attachments[projectAttachmentIndex].url = eachAttachment.url; + } + }) + } + } + + if ( projectLinkAttachments && projectLinkAttachments.length > 0 ) { + project.attachments.concat(projectLinkAttachments); + } + } + project.status = project.status ? project.status : CONSTANTS.common.NOT_STARTED_STATUS; From d6c850d0c73145d115e8681b1accfa5bdc041ac7 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 22 Feb 2022 10:19:07 +0530 Subject: [PATCH 090/373] cache file --- generics/helpers/cache.js | 62 +++++++++++++++++++++++++++++++++++++++ package.json | 9 +++--- 2 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 generics/helpers/cache.js diff --git a/generics/helpers/cache.js b/generics/helpers/cache.js new file mode 100644 index 00000000..603d1a29 --- /dev/null +++ b/generics/helpers/cache.js @@ -0,0 +1,62 @@ +/** + * name : cache.js + * author : Priyanka Pradeep + * created-date : 21-Feb-2020 + * Description : Cache set , get and remove functionality. + */ + + const nodeCache = require( "node-cache" ); + const cache = new nodeCache(); + + /** + * Get cache data. + * @method + * @name get - Get specific cache data + * @params key - name of the cache key. + * @returns {Array} - return specific cache data. +*/ + +function getValue(key){ + let data = []; + + if (cache.has(key)) { + data = cache.get(key); + } + + return data; +} + + + /** + * Set new cache data + * @method + * @name set + * @params key - name of the cache key. + * @params value - cache data to set. + * @returns {Array} - cache updated data. +*/ + +function setValue(key, value, timeout){ + let data = cache.set( key, value, timeout ); + return data; +} + +/** + * delete cache data + * @method + * @name remove + * @params key - cache key need to be removed. + * @returns +*/ + +function removeKey(key){ + + let data = cache.del(key); + return; +} + +module.exports = { + getValue : getValue, + setValue : setValue, + removeKey : removeKey +} \ No newline at end of file diff --git a/package.json b/package.json index a7afd220..ab919560 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,8 @@ "bunyan": "^1.8.12", "bunyan-format": "^0.2.1", "cache-manager": "^3.1.0", + "chai": "^4.2.0", + "chai-http": "^4.3.0", "cli-table": "^0.3.1", "cors": "^2.8.5", "csvtojson": "^2.0.10", @@ -49,21 +51,20 @@ "keycloak-auth-utils": "^3.3.0", "lodash": "^4.17.15", "log": "^1.4.0", + "mocha": "^6.2.2", "moment-timezone": "^0.5.31", "mongoose": "^5.9.4", "mongoose-autopopulate": "^0.12.0", "mongoose-delete": "^0.5.1", "mongoose-timestamp": "^0.6.0", "mongoose-ttl": "0.0.3", + "node-cache": "^5.1.2", "p-each-series": "^2.1.0", "path": "^0.12.7", "request": "^2.88.2", "require-all": "^3.0.0", "uuid": "^8.3.0", - "xml-js": "^1.6.11", - "chai": "^4.2.0", - "chai-http": "^4.3.0", - "mocha": "^6.2.2" + "xml-js": "^1.6.11" }, "devDependencies": { "grunt-apidoc": "^0.11.0", From efb2558bf5780d0fd86e5423b592cb4ab6250882 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Fri, 25 Feb 2022 16:04:24 +0530 Subject: [PATCH 091/373] Add submission information --- module/userProjects/helper.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 8dbaca11..05f461d4 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -758,7 +758,14 @@ module.exports = class UserProjectsHelper { data["submissionStatus"] = CONSTANTS.common.STARTED; - let submissionDetails = currentTask.observationInformation ? currentTask.observationInformation : {}; + // For 4.7 Urgent fix, need to check why observationInformation is not present at task level. + let submissionDetails = {}; + if(currentTask.observationInformation) { + submissionDetails = currentTask.observationInformation + } else if (currentTask.submissionDetails) { + submissionDetails = currentTask.submissionDetails + } + data["submissionDetails"] = submissionDetails; if ( currentTask.submissions && currentTask.submissions.length > 0 ) { From e9ff4515f52ea01d0d8f926b224abf1be452ed1f Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Fri, 25 Feb 2022 19:34:33 +0530 Subject: [PATCH 092/373] Remove referenceFrom filter key from the query for importedProjects. --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 05f461d4..d550ef15 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1766,7 +1766,7 @@ module.exports = class UserProjectsHelper { let filterQuery = { userId : userId, - referenceFrom : { $exists : true,$eq : CONSTANTS.common.OBSERVATION_REFERENCE_KEY }, + // referenceFrom : { $exists : true,$eq : CONSTANTS.common.OBSERVATION_REFERENCE_KEY }, - Commented as this filter is not useful. - 4.7 Sprint - 25Feb2022 isDeleted: false }; From eca99b7aef74e524cea94d6c3d079e89e8a6e480 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Sun, 27 Feb 2022 21:58:18 +0530 Subject: [PATCH 093/373] project & task attchments --- generics/constants/common.js | 4 +- module/userProjects/helper.js | 237 +++++++++++++++++++--------------- 2 files changed, 139 insertions(+), 102 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index 52c7fd75..009bf7e9 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -42,5 +42,7 @@ module.exports = { "DEFAULT_SUBMISSION_REQUIRED" : 1, "TASK_SEQUENCE" : "taskSequence", "CHILDREN" : "children", - "ATTACHMENT_TYPE_LINK" : "link" + "ATTACHMENT_TYPE_LINK" : "link", + "PROJECT_ATTACHMENT" : "project", + "TASK_ATTACHMENT" : "task" }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 44a3cc23..bdbdf76f 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2073,6 +2073,34 @@ function _projectInformation(project) { project.programName = project.programInformation.name; } + //project attachments + if ( project.attachments && project.attachments.length > 0 ) { + + let projectLinkAttachments = []; + let projectAttachments = []; + + for ( + let pointerToAttachment = 0; + pointerToAttachment < project.attachments.length; + pointerToAttachment++ + ) { + + let currentProjectAttachment = project.attachments[pointerToAttachment]; + if ( currentProjectAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { + projectLinkAttachments.push(currentProjectAttachment); + } else { + projectAttachments.push(currentProjectAttachment.sourcePath); + } + } + + let projectAttachmentsUrl = await _attachmentInformation(projectAttachments, projectLinkAttachments, project.attachments, CONSTANTS.common.PROJECT_ATTACHMENT); + if ( projectAttachmentsUrl.data && projectAttachmentsUrl.data.length > 0 ) { + project.attachments = projectAttachmentsUrl.data; + } + + } + + //task attachments if (project.tasks && project.tasks.length > 0) { //order task based on task sequence if ( project.taskSequence && project.taskSequence.length > 0 ) { @@ -2095,8 +2123,7 @@ function _projectInformation(project) { ) { let currentAttachment = currentTask.attachments[attachment]; - //remove link attachment from task attachments - if (currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { + if (currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { if (!Array.isArray(mapLinkAttachment[currentTask._id]) || !mapLinkAttachment[currentTask._id].length ) { mapLinkAttachment[currentTask._id] = []; } @@ -2112,107 +2139,11 @@ function _projectInformation(project) { } } } - - } - - if (attachments.length > 0) { - - let attachmentsUrl = - await coreService.getDownloadableUrl( - { - filePaths: attachments - } - ); - - if (!attachmentsUrl.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND - } - } - - if (attachmentsUrl.data.length > 0) { - attachmentsUrl.data.forEach(attachmentUrl => { - - let taskIndex = - project.tasks.findIndex(task => task._id === mapTaskIdToAttachment[attachmentUrl.filePath].taskId); - - if (taskIndex > -1) { - let attachmentIndex = - project.tasks[taskIndex].attachments.findIndex(attachment => attachment.sourcePath === attachmentUrl.filePath); - - if (attachmentIndex > -1) { - project.tasks[taskIndex].attachments[attachmentIndex].url = attachmentUrl.url; - } - } - }) - } - - } - - //add link attachment to task attachments - if ( mapLinkAttachment && Object.keys(mapLinkAttachment).length > 0 ) { - - Object.keys(mapLinkAttachment).forEach(eachTaskId => { - - let taskIdIndex = project.tasks.findIndex(task => task._id === eachTaskId); - if ( taskIdIndex > -1 ) { - project.tasks[taskIdIndex].attachments.concat(mapLinkAttachment[eachTaskId]); - } - }) - } - } - - //project attachments - if ( project.attachments && project.attachments.length > 0 ) { - - let projectLinkAttachments = []; - let projectAttachments = []; - - for ( - let pointerToAttachment = 0; - pointerToAttachment < project.attachments.length; - pointerToAttachment++ - ) { - - let currentProjectAttachment = project.attachments[pointerToAttachment]; - if ( currentProjectAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { - projectLinkAttachments.push(currentProjectAttachment); - } else { - projectAttachments.push(currentProjectAttachment.sourcePath); - } - } - - if ( projectAttachments && projectAttachments.length > 0 ) { - - let projectAttachmentsUrl = - await coreService.getDownloadableUrl( - { - filePaths: projectAttachments - } - ); - - if (!projectAttachmentsUrl.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND - } - } - - if (projectAttachmentsUrl.data.length > 0) { - projectAttachmentsUrl.data.forEach(eachAttachment => { - let projectAttachmentIndex = - project.attachments.findIndex(attachmentData => attachmentData.sourcePath == eachAttachment.filePath); - console.log(projectAttachmentIndex,"projectAttachmentIndex") - if (projectAttachmentIndex > -1) { - project.attachments[projectAttachmentIndex].url = eachAttachment.url; - } - }) - } } - if ( projectLinkAttachments && projectLinkAttachments.length > 0 ) { - project.attachments.concat(projectLinkAttachments); + let taskAttachmentsUrl = await _attachmentInformation(attachments, mapLinkAttachment, [], CONSTANTS.common.TASK_ATTACHMENT, mapTaskIdToAttachment, project.tasks); + if ( taskAttachmentsUrl.data && taskAttachmentsUrl.data.length > 0 ) { + project.tasks = taskAttachmentsUrl.data; } } @@ -2254,6 +2185,110 @@ function taskArrayBySequence (taskArray, sequenceArray, key) { return sortedTaskArray }; +/** + * Attachment information of project. + * @method + * @name _attachmentInformation + * @param {Array} attachments - attachments data. + * @param {String} type - project or task attachement. + * @returns {Object} Project attachments. +*/ +function _attachmentInformation ( attachmentWithSourcePath = [], linkAttachments = [], attachments = [] , type, mapTaskIdToAttachment = {}, tasks = []) { + return new Promise(async (resolve, reject) => { + try { + + let attachmentOrTask = []; + + if ( attachmentWithSourcePath && attachmentWithSourcePath.length > 0 ) { + + let attachmentsUrl = + await coreService.getDownloadableUrl( + { + filePaths: attachmentWithSourcePath + } + ); + + if (!attachmentsUrl.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND + } + } + + if ( attachmentsUrl.data && attachmentsUrl.data.length > 0) { + + if (type === CONSTANTS.common.PROJECT_ATTACHMENT ) { + + attachmentsUrl.data.forEach(eachAttachment => { + + let projectAttachmentIndex = + attachments.findIndex(attachmentData => attachmentData.sourcePath == eachAttachment.filePath); + + if (projectAttachmentIndex > -1) { + attachments[projectAttachmentIndex].url = eachAttachment.url; + } + }) + + } else { + + attachmentsUrl.data.forEach(taskAttachments => { + + let taskIndex = + tasks.findIndex(task => task._id === mapTaskIdToAttachment[taskAttachments.filePath].taskId); + + if (taskIndex > -1) { + + let attachmentIndex = + tasks[taskIndex].attachments.findIndex(attachment => attachment.sourcePath === taskAttachments.filePath); + + if (attachmentIndex > -1) { + tasks[taskIndex].attachments[attachmentIndex].url = taskAttachments.url; + } + } + }) + } + } + } + + if ( linkAttachments && linkAttachments.length > 0 ) { + + if (type === CONSTANTS.common.PROJECT_ATTACHMENT ) { + attachments.concat(linkAttachments); + + } else { + + Object.keys(linkAttachments).forEach(eachTaskId => { + + let taskIdIndex = tasks.findIndex(task => task._id === eachTaskId); + if ( taskIdIndex > -1 ) { + tasks[taskIdIndex].attachments.concat(linkAttachments[eachTaskId]); + } + }) + + } + } + + attachmentOrTask = (type === CONSTANTS.common.PROJECT_ATTACHMENT) ? attachments : tasks + + return resolve({ + success: true, + data: attachmentOrTask + }); + + } catch (error) { + + return resolve({ + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) + } + + }) +} + /** * Task of project. * @method From b9cd175582d8030edaf3cf238d7d4e96d93522b8 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 28 Feb 2022 13:34:11 +0530 Subject: [PATCH 094/373] fix task --- module/userProjects/helper.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index d550ef15..13077818 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -275,6 +275,10 @@ module.exports = class UserProjectsHelper { if (userProject[0].tasks[taskIndex].submissions) { task.submissions = userProject[0].tasks[taskIndex].submissions; } + + if (userProject[0].tasks[taskIndex].observationInformation) { + task.observationInformation = userProject[0].tasks[taskIndex].observationInformation; + } userProject[0].tasks[taskIndex] = task; } From 917fd935d964d6cae44e4f8731bbf149f304a565 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 2 Mar 2022 11:24:03 +0530 Subject: [PATCH 095/373] fix submissionDetails --- module/userProjects/helper.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 13077818..11fddd9c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -279,6 +279,10 @@ module.exports = class UserProjectsHelper { if (userProject[0].tasks[taskIndex].observationInformation) { task.observationInformation = userProject[0].tasks[taskIndex].observationInformation; } + + if (userProject[0].tasks[taskIndex].submissionDetails) { + delete userProject[0].tasks[taskIndex].submissionDetails; + } userProject[0].tasks[taskIndex] = task; } @@ -2240,6 +2244,10 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { } } + if (singleTask.submissionDetails) { + delete singleTask.submissionDetails; + } + if (singleTask.children) { _projectTask( singleTask.children, From 5887d86795b0440b1ec9a832dd2e65d40eabeeac Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 2 Mar 2022 13:04:07 +0530 Subject: [PATCH 096/373] fix submissionDetails --- module/userProjects/helper.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 11fddd9c..82df5e05 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -271,18 +271,17 @@ module.exports = class UserProjectsHelper { task ); } else { - - if (userProject[0].tasks[taskIndex].submissions) { - task.submissions = userProject[0].tasks[taskIndex].submissions; - } - if (userProject[0].tasks[taskIndex].observationInformation) { - task.observationInformation = userProject[0].tasks[taskIndex].observationInformation; - } + let removeFieldsFromRequest = ["submissionDetails"]; + let keepFieldsFromTask = ["observationInformation", "submissions"]; + + removeFieldsFromRequest.forEach((removeField) => { + delete userProject[0].tasks[taskIndex][removeField]; + }); - if (userProject[0].tasks[taskIndex].submissionDetails) { - delete userProject[0].tasks[taskIndex].submissionDetails; - } + keepFieldsFromTask.forEach((field) => { + task.field = userProject[0].tasks[taskIndex][field] ? userProject[0].tasks[taskIndex][field] : null; + }); userProject[0].tasks[taskIndex] = task; } From 53fccfe781313aa31217640c9d5a44b91772775a Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 2 Mar 2022 14:33:20 +0530 Subject: [PATCH 097/373] fix --- module/userProjects/helper.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 82df5e05..c85e668f 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2243,9 +2243,11 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { } } - if (singleTask.submissionDetails) { + let removeFieldsFromRequest = ["submissionDetails"]; + + removeFieldsFromRequest.forEach((removeField) => { delete singleTask.submissionDetails; - } + }); if (singleTask.children) { _projectTask( From d338861e3610786602020358df0ffb5578464439 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 2 Mar 2022 14:38:17 +0530 Subject: [PATCH 098/373] fix --- module/userProjects/helper.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c85e668f..8d52fdb8 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -137,6 +137,8 @@ module.exports = class UserProjectsHelper { }; } + let removeFieldsFromRequest = ["submissionDetails"]; + const projectsModel = Object.keys(schemas["projects"].schema); let updateProject = {}; @@ -248,7 +250,10 @@ module.exports = class UserProjectsHelper { let taskReport = {}; updateProject.tasks = await _projectTask( - data.tasks + data.tasks, + false, + "", + removeFieldsFromRequest ); if ( @@ -272,7 +277,6 @@ module.exports = class UserProjectsHelper { ); } else { - let removeFieldsFromRequest = ["submissionDetails"]; let keepFieldsFromTask = ["observationInformation", "submissions"]; removeFieldsFromRequest.forEach((removeField) => { @@ -2207,7 +2211,7 @@ function taskArrayBySequence (taskArray, sequenceArray, key) { * @returns {Object} Project task. */ -function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { +function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "", removeFieldsFromRequest = []) { tasks.forEach(singleTask => { @@ -2242,13 +2246,14 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { }); } } - - let removeFieldsFromRequest = ["submissionDetails"]; - removeFieldsFromRequest.forEach((removeField) => { - delete singleTask.submissionDetails; - }); + if ( removeFieldsFromRequest && removeFieldsFromRequest.length > 0 ) { + removeFieldsFromRequest.forEach((removeField) => { + delete singleTask[removeField]; + }); + } + if (singleTask.children) { _projectTask( singleTask.children, From 51e405ae61964127cb85ae9de2bcc6c61bb6aaa4 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 2 Mar 2022 14:45:00 +0530 Subject: [PATCH 099/373] fix --- module/userProjects/helper.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 8d52fdb8..5edc43dd 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -18,8 +18,8 @@ const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); - const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); +const removeFieldsFromRequest = ["submissionDetails"]; /** * UserProjectsHelper @@ -137,8 +137,6 @@ module.exports = class UserProjectsHelper { }; } - let removeFieldsFromRequest = ["submissionDetails"]; - const projectsModel = Object.keys(schemas["projects"].schema); let updateProject = {}; From c0c9501181c2be56e9185a3000a3bef6e8899977 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 2 Mar 2022 14:47:25 +0530 Subject: [PATCH 100/373] fix --- module/userProjects/helper.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 5edc43dd..00604fbc 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -248,10 +248,7 @@ module.exports = class UserProjectsHelper { let taskReport = {}; updateProject.tasks = await _projectTask( - data.tasks, - false, - "", - removeFieldsFromRequest + data.tasks ); if ( @@ -2209,7 +2206,7 @@ function taskArrayBySequence (taskArray, sequenceArray, key) { * @returns {Object} Project task. */ -function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "", removeFieldsFromRequest = []) { +function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { tasks.forEach(singleTask => { @@ -2245,12 +2242,9 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "", r } } - if ( removeFieldsFromRequest && removeFieldsFromRequest.length > 0 ) { - - removeFieldsFromRequest.forEach((removeField) => { - delete singleTask[removeField]; - }); - } + removeFieldsFromRequest.forEach((removeField) => { + delete singleTask[removeField]; + }); if (singleTask.children) { _projectTask( From cf79ba6292e4dc8618f1af7502e697f0e651b6f3 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 4 Mar 2022 19:32:37 +0530 Subject: [PATCH 101/373] codition check and response data are changed --- module/userProjects/helper.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 8dbaca11..cdfcf026 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -535,7 +535,7 @@ module.exports = class UserProjectsHelper { return resolve(result); } - console.log("Project information is",result); + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, @@ -1352,7 +1352,7 @@ module.exports = class UserProjectsHelper { let createNewProgramAndSolution = false; if (data.programId && data.programId !== "") { - createNewProgramAndSolution = true; + createNewProgramAndSolution = false; } else if (data.programName) { createNewProgramAndSolution = true; @@ -1467,7 +1467,7 @@ module.exports = class UserProjectsHelper { data: { programId: userProject.programInformation && userProject.programInformation._id ? - userProject.programInformation._id : "", + userProject.programInformation._id : data.programId, projectId: userProject._id, lastDownloadedAt: userProject.lastDownloadedAt, hasAcceptedTAndC : userProject.hasAcceptedTAndC ? userProject.hasAcceptedTAndC : false @@ -2159,7 +2159,7 @@ function _projectInformation(project) { delete project.solutionInformation; delete project.programInformation; - console.log("project data is",project); + return resolve({ success: true, From 56c9a5f089fa478c669fe74b147c60c279b6884b Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 4 Mar 2022 22:29:20 +0530 Subject: [PATCH 102/373] Condition and response changes in userProjects helper --- module/userProjects/helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6e224240..6ca8a5f5 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1364,7 +1364,7 @@ module.exports = class UserProjectsHelper { let createNewProgramAndSolution = false; if (data.programId && data.programId !== "") { - createNewProgramAndSolution = true; + createNewProgramAndSolution = false; } else if (data.programName) { createNewProgramAndSolution = true; @@ -1479,7 +1479,7 @@ module.exports = class UserProjectsHelper { data: { programId: userProject.programInformation && userProject.programInformation._id ? - userProject.programInformation._id : "", + userProject.programInformation._id : data.programId, projectId: userProject._id, lastDownloadedAt: userProject.lastDownloadedAt, hasAcceptedTAndC : userProject.hasAcceptedTAndC ? userProject.hasAcceptedTAndC : false From add47c4ed6aa1e0d55d6423845c5026fd9b64a75 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 9 Mar 2022 11:01:37 +0530 Subject: [PATCH 103/373] multiple program getting created problem- Resolve --- controllers/v1/programs.js | 15 +++++++++ databaseQueries/programs.js | 62 +++++++++++++++++++++++++++++++++++ models/programs.js | 52 +++++++++++++++++++++++++++++ module/userProjects/helper.js | 42 +++++++++++++++++------- 4 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 controllers/v1/programs.js create mode 100644 databaseQueries/programs.js create mode 100644 models/programs.js diff --git a/controllers/v1/programs.js b/controllers/v1/programs.js new file mode 100644 index 00000000..9e89755e --- /dev/null +++ b/controllers/v1/programs.js @@ -0,0 +1,15 @@ +/** + * name : programs.js + * author : vishnu + * created-date : 09-Mar-2022 + * Description : programs related information. + */ +module.exports = class Programs extends Abstract{ + constructor() { + super("programs"); + } + + static get name() { + return "programs"; + } +} \ No newline at end of file diff --git a/databaseQueries/programs.js b/databaseQueries/programs.js new file mode 100644 index 00000000..1fb184d9 --- /dev/null +++ b/databaseQueries/programs.js @@ -0,0 +1,62 @@ +/** + * name : solutions.js + * author : Vishnu + * created-date : 09-Mar-2022 + * Description : program helper for DB interactions. + */ + +// Dependencies + +/** + * Programs + * @class +*/ + + + +module.exports= class Programs{ + /** + * programs details. + * @method + * @name programsDocument + * @param {Array} [filterData = "all"] - programs filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} program details. + */ + + static programsDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + let programsDoc = + await database.models.programs.find( + queryObject, + projection + ).lean(); + + return resolve(programsDoc); + + } catch (error) { + return reject(error); + } + }); + } +} \ No newline at end of file diff --git a/models/programs.js b/models/programs.js new file mode 100644 index 00000000..2e934c54 --- /dev/null +++ b/models/programs.js @@ -0,0 +1,52 @@ +/** + * name : programs-model.js. + * author : Vishnu. + * created-date : 09-Mar-2022. + * Description : Schema for programs. + */ +module.exports = { + name: "programs", + schema: { + externalId: String, + name: String, + description: String, + owner: String, + createdBy: String, + updatedBy: String, + status: { + type : String, + index : true + }, + resourceType: [String], + language: [String], + keywords: [String], + concepts: ["json"], + imageCompression: {}, + components: ["json"], + components: ["json"], + isAPrivateProgram : { + default : false, + type : Boolean + }, + scope : { + entityType : String, + entityTypeId : "ObjectId", + entities : { + type : Array, + index : true + }, + roles : [{ + _id : "ObjectId", + code : { + type : String, + index : true + } + }] + }, + isDeleted: { + default : false, + type : Boolean, + index : true + } + } + }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6ca8a5f5..c2856794 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -20,6 +20,7 @@ const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates") const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; +const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); /** * UserProjectsHelper @@ -99,7 +100,7 @@ module.exports = class UserProjectsHelper { static sync(projectId, lastDownloadedAt, data, userId, userToken, appName = "", appVersion = "") { return new Promise(async (resolve, reject) => { try { - + const userProject = await projectQueries.projectDocument({ _id: projectId, userId: userId @@ -114,7 +115,7 @@ module.exports = class UserProjectsHelper { "appInformation", "status" ]); - + if (!userProject.length > 0) { throw { @@ -144,16 +145,14 @@ module.exports = class UserProjectsHelper { if (projectData && projectData.success == true) { updateProject = _.merge(updateProject, projectData.data); } - let createNewProgramAndSolution = false; let solutionExists = false; if (data.programId && data.programId !== "") { // Check if program already existed in project and if its not an existing program. - if (!userProject[0].programInformation) { - createNewProgramAndSolution = true; + createNewProgramAndSolution = true; } else if ( userProject[0].programInformation && userProject[0].programInformation._id && @@ -161,7 +160,7 @@ module.exports = class UserProjectsHelper { ) { // Not an existing program. - solutionExists = true; + solutionExists = true; } } else if (data.programName) { @@ -202,9 +201,9 @@ module.exports = class UserProjectsHelper { updateProject["entityInformation"] = entityInformation.data[0]; updateProject.entityId = entityInformation.data[0]._id; } - + if (createNewProgramAndSolution || solutionExists) { - + let programAndSolutionInformation = await this.createProgramAndSolution( data.programId, @@ -1369,7 +1368,7 @@ module.exports = class UserProjectsHelper { else if (data.programName) { createNewProgramAndSolution = true; } - + if (data.entityId) { let entityInformation = await _entitiesInformation([data.entityId]); @@ -1394,9 +1393,29 @@ module.exports = class UserProjectsHelper { if (!programAndSolutionInformation.success) { return resolve(programAndSolutionInformation); } - createProject = _.merge(createProject, programAndSolutionInformation.data); + } else { + let queryData = {}; + queryData["_id"] = data.programId; + let programDetails = await programsQueries.programsDocument(queryData, + [ + "_id", + "name", + "description", + "isAPrivateProgram" + ] + ); + if( !programDetails.length > 0 ){ + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND + }; + } + let programInformationData = {}; + programInformationData["programInformation"] = programDetails[0]; + createProject = + _.merge(createProject, programInformationData); } if (data.tasks) { @@ -1459,11 +1478,10 @@ module.exports = class UserProjectsHelper { } createProject.status = UTILS.convertProjectStatus(data.status); - let userProject = await projectQueries.createProject( createProject ); - + await kafkaProducersHelper.pushProjectToKafka(userProject); if (!userProject._id) { From 690955ceb37a2760a630133727a6605fac606348 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 9 Mar 2022 12:25:16 +0530 Subject: [PATCH 104/373] SB-29009 resolve for 4.7 --- controllers/v1/programs.js | 15 +++++++++ databaseQueries/programs.js | 62 +++++++++++++++++++++++++++++++++++ models/programs.js | 52 +++++++++++++++++++++++++++++ module/userProjects/helper.js | 23 +++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 controllers/v1/programs.js create mode 100644 databaseQueries/programs.js create mode 100644 models/programs.js diff --git a/controllers/v1/programs.js b/controllers/v1/programs.js new file mode 100644 index 00000000..9e89755e --- /dev/null +++ b/controllers/v1/programs.js @@ -0,0 +1,15 @@ +/** + * name : programs.js + * author : vishnu + * created-date : 09-Mar-2022 + * Description : programs related information. + */ +module.exports = class Programs extends Abstract{ + constructor() { + super("programs"); + } + + static get name() { + return "programs"; + } +} \ No newline at end of file diff --git a/databaseQueries/programs.js b/databaseQueries/programs.js new file mode 100644 index 00000000..d16ccfe6 --- /dev/null +++ b/databaseQueries/programs.js @@ -0,0 +1,62 @@ +/** + * name : programs.js + * author : Vishnu + * created-date : 09-Mar-2022 + * Description : program helper for DB interactions. + */ + +// Dependencies + +/** + * Programs + * @class +*/ + + + +module.exports= class Programs{ + /** + * programs details. + * @method + * @name programsDocument + * @param {Array} [filterData = "all"] - programs filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} program details. + */ + + static programsDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + let programsDoc = + await database.models.programs.find( + queryObject, + projection + ).lean(); + + return resolve(programsDoc); + + } catch (error) { + return reject(error); + } + }); + } +} \ No newline at end of file diff --git a/models/programs.js b/models/programs.js new file mode 100644 index 00000000..0f8a89a8 --- /dev/null +++ b/models/programs.js @@ -0,0 +1,52 @@ +/** + * name : programs-model.js. + * author : Vishnu. + * created-date : 09-Mar-2022. + * Description : Schema for programs. + */ + module.exports = { + name: "programs", + schema: { + externalId: String, + name: String, + description: String, + owner: String, + createdBy: String, + updatedBy: String, + status: { + type : String, + index : true + }, + resourceType: [String], + language: [String], + keywords: [String], + concepts: ["json"], + imageCompression: {}, + components: ["json"], + components: ["json"], + isAPrivateProgram : { + default : false, + type : Boolean + }, + scope : { + entityType : String, + entityTypeId : "ObjectId", + entities : { + type : Array, + index : true + }, + roles : [{ + _id : "ObjectId", + code : { + type : String, + index : true + } + }] + }, + isDeleted: { + default : false, + type : Boolean, + index : true + } + } + }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index cdfcf026..c0c32710 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -18,6 +18,7 @@ const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); +const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); @@ -1385,7 +1386,29 @@ module.exports = class UserProjectsHelper { createProject = _.merge(createProject, programAndSolutionInformation.data); + }else { + let queryData = {}; + queryData["_id"] = data.programId; + let programDetails = await programsQueries.programsDocument(queryData, + [ + "_id", + "name", + "description", + "isAPrivateProgram" + ] + ); + if( !programDetails.length > 0 ){ + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND + }; + } + let programInformationData = {}; + programInformationData["programInformation"] = programDetails[0]; + createProject = + _.merge(createProject, programInformationData); } + if (data.tasks) { From 00ea220b3072b4248f5ec67ea85787dd5d12380a Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 10 Mar 2022 12:08:24 +0530 Subject: [PATCH 105/373] add project quick fix --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c2856794..52e1acf7 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1395,7 +1395,8 @@ module.exports = class UserProjectsHelper { } createProject = _.merge(createProject, programAndSolutionInformation.data); - } else { + } + if( data.programId && data.programId !== "" ){ let queryData = {}; queryData["_id"] = data.programId; let programDetails = await programsQueries.programsDocument(queryData, From 5c3ea4657f930161413e253363ef34577430187f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 10 Mar 2022 12:19:19 +0530 Subject: [PATCH 106/373] quick fix --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c0c32710..d1259436 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1386,7 +1386,8 @@ module.exports = class UserProjectsHelper { createProject = _.merge(createProject, programAndSolutionInformation.data); - }else { + } + if (data.programId && data.programId !== "") { let queryData = {}; queryData["_id"] = data.programId; let programDetails = await programsQueries.programsDocument(queryData, From a2fe46c8d4a93741dff6591a725ed3fe0f7fc6af Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 10 Mar 2022 12:19:26 +0530 Subject: [PATCH 107/373] fix task --- module/userProjects/helper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c2856794..cafd5b0c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -278,7 +278,9 @@ module.exports = class UserProjectsHelper { }); keepFieldsFromTask.forEach((field) => { - task.field = userProject[0].tasks[taskIndex][field] ? userProject[0].tasks[taskIndex][field] : null; + if ( userProject[0].tasks[taskIndex][field] ){ + task[field] = userProject[0].tasks[taskIndex][field]; + } }); userProject[0].tasks[taskIndex] = task; From effc077a013e3d204b91d502b334cb58cdc89c0d Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 10 Mar 2022 12:52:47 +0530 Subject: [PATCH 108/373] task fix --- module/userProjects/helper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 70ad09e3..8789d5fa 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -282,7 +282,9 @@ module.exports = class UserProjectsHelper { }); keepFieldsFromTask.forEach((field) => { - task.field = userProject[0].tasks[taskIndex][field] ? userProject[0].tasks[taskIndex][field] : null; + if ( userProject[0].tasks[taskIndex][field] ){ + task[field] = userProject[0].tasks[taskIndex][field]; + } }); userProject[0].tasks[taskIndex] = task; From 881ca49cf2c97884c4eef4bbdfd34d4c8c15f6a1 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 16 Mar 2022 12:01:57 +0530 Subject: [PATCH 109/373] eG changes --- models/projects.js | 2 +- module/reports/helper.js | 29 ++++++++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/models/projects.js b/models/projects.js index 597b8d2d..80cd51a1 100644 --- a/models/projects.js +++ b/models/projects.js @@ -83,7 +83,7 @@ module.exports = { default : [] }, entityId : { - type : "ObjectId", + type : String, index : true }, programId : { diff --git a/module/reports/helper.js b/module/reports/helper.js index e49a5793..aedd3109 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -39,12 +39,19 @@ module.exports = class ReportsHelper { try { let query = { }; + //eG code if (entityId) { - query["entityId"] = ObjectId(entityId); + query["entityId"] = entityId; } else { query["userId"] = userId } + // if (entityId) { + // query["entityId"] = ObjectId(entityId); + // } else { + // query["userId"] = userId + // } + let dateRange = await _getDateRangeofReport(reportType); let endOf = dateRange.endOf; let startFrom = dateRange.startFrom; @@ -64,14 +71,14 @@ module.exports = class ReportsHelper { { "syncedAt": { $gte: new Date(startFrom), $lte: new Date(endOf) } }, { "tasks": { $elemMatch: { isDeleted: { $ne: true },syncedAt: { $gte: new Date(startFrom), $lte: new Date(endOf) } } } }, ] - + console.log("Query : ",query) const projectDetails = await projectQueries.projectDocument( query, ["programId","programInformation.name", "entityInformation.name", "taskReport", "status", "tasks", "categories"], [] ); - + console.log("projectDetails : ",projectDetails) let tasksReport = { "total": 0, "overdue": 0 @@ -318,7 +325,9 @@ module.exports = class ReportsHelper { } } catch (error) { + console.log("error : ",error) return resolve({ + success: false, message: error.message, data: false @@ -352,9 +361,9 @@ module.exports = class ReportsHelper { $exists : true } }; - - if(entityId != "" && UTILS.isValidMongoId(entityId)) { - query.entityId = ObjectId(entityId); + + if( entityId != "" ) { + query.entityId = entityId; } if (userRole != "") { @@ -484,11 +493,17 @@ module.exports = class ReportsHelper { }; if (entityId) { - query["entityId"] = ObjectId(entityId); + query["entityId"] = entityId; } else { query["userId"] = userId } + // if (entityId) { + // query["entityId"] = ObjectId(entityId); + // } else { + // query["userId"] = userId + // } + let chartObject = []; let dateRange = await _getDateRangeofReport(reportType); let endOf = dateRange.endOf; From 254e497602a055a6c95db782fd0ec3cb606e3a38 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 21 Mar 2022 09:54:13 +0530 Subject: [PATCH 110/373] eG monday 22 --- generics/constants/common.js | 5 +- generics/constants/endpoints.js | 3 +- module/userProjects/helper.js | 239 +++++++++++++++++++++++++++++--- 3 files changed, 227 insertions(+), 20 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index 009bf7e9..8b72cbe7 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -44,5 +44,8 @@ module.exports = { "CHILDREN" : "children", "ATTACHMENT_TYPE_LINK" : "link", "PROJECT_ATTACHMENT" : "project", - "TASK_ATTACHMENT" : "task" + "TASK_ATTACHMENT" : "task", + "SUNBIRD_SERVER_TIMEOUT" : 5000, + "TIMEOUT_ERROR" : "Server timeout error", + "OK" : "OK" }; diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 4a249318..11e6ea9c 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -44,5 +44,6 @@ module.exports = { LIST_ENTITIES_BY_LOCATION_IDS : "/v1/entities/listByLocationIds", CREATE_IMPROVEMENT_PROJECT_SOLUTION : "/v1/solutions/create", PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport", - FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl" + FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl", + GET_LOCATION_DATA : "/api/data/v1/location/search" }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c2856794..6b1779df 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,6 +21,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); +const sunbirdService = require(GENERICS_FILES_PATH + '/services/sunbird'); /** * UserProjectsHelper @@ -176,7 +177,7 @@ module.exports = class UserProjectsHelper { let addOrUpdateEntityToProject = false; if (data.entityId) { - + console.log("#####here") // If entity is not present in project or new entity is updated. if ( !userProject[0].entityInformation || @@ -188,7 +189,7 @@ module.exports = class UserProjectsHelper { addOrUpdateEntityToProject = true; } } - + console.log(" addOrUpdateEntityToProject : ", addOrUpdateEntityToProject) if (addOrUpdateEntityToProject) { let entityInformation = @@ -201,7 +202,7 @@ module.exports = class UserProjectsHelper { updateProject["entityInformation"] = entityInformation.data[0]; updateProject.entityId = entityInformation.data[0]._id; } - + console.log("updateProject.entityId : ",updateProject.entityId ) if (createNewProgramAndSolution || solutionExists) { let programAndSolutionInformation = @@ -912,7 +913,7 @@ module.exports = class UserProjectsHelper { "projectTemplateId" ] ); - + console.log("project details : ",project) if (!project.length > 0) { throw { status: HTTP_STATUS_CODE['bad_request'].status, @@ -1349,7 +1350,6 @@ module.exports = class UserProjectsHelper { static add(data, userId, userToken, appName = "", appVersion = "") { return new Promise(async (resolve, reject) => { try { - const projectsModel = Object.keys(schemas["projects"].schema); let createProject = {}; @@ -1395,7 +1395,7 @@ module.exports = class UserProjectsHelper { } createProject = _.merge(createProject, programAndSolutionInformation.data); - } else { + } else{ let queryData = {}; queryData["_id"] = data.programId; let programDetails = await programsQueries.programsDocument(queryData, @@ -1504,6 +1504,160 @@ module.exports = class UserProjectsHelper { } }); + // const projectsModel = Object.keys(schemas["projects"].schema); + // let createProject = {}; + + // createProject["userId"] = createProject["createdBy"] = createProject["updatedBy"] = userId; + + // let projectData = await _projectData(data); + // if (projectData && projectData.success == true) { + // createProject = _.merge(createProject, projectData.data); + // } + + // let createNewProgramAndSolution = false; + + // if (data.programId && data.programId !== "") { + // createNewProgramAndSolution = false; + // } + // else if (data.programName) { + // createNewProgramAndSolution = true; + // } + + // if (data.entityId) { + // let entityInformation = + // await _entitiesInformation([data.entityId]); + + // if (!entityInformation.success) { + // return resolve(entityInformation); + // } + + // createProject["entityInformation"] = entityInformation.data[0]; + // createProject.entityId = entityInformation.data[0]._id; + // } + // if (createNewProgramAndSolution) { + + // let programAndSolutionInformation = + // await this.createProgramAndSolution( + // data.programId, + // data.programName, + // createProject.entityId ? [createProject.entityId] : "", + // userToken + // ); + + // if (!programAndSolutionInformation.success) { + // return resolve(programAndSolutionInformation); + // } + // createProject = + // _.merge(createProject, programAndSolutionInformation.data); + // } else { + // let queryData = {}; + // queryData["_id"] = data.programId; + // let programDetails = await programsQueries.programsDocument(queryData, + // [ + // "_id", + // "name", + // "description", + // "isAPrivateProgram" + // ] + // ); + // if( !programDetails.length > 0 ){ + // throw { + // status: HTTP_STATUS_CODE['bad_request'].status, + // message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND + // }; + // } + // let programInformationData = {}; + // programInformationData["programInformation"] = programDetails[0]; + // createProject = + // _.merge(createProject, programInformationData); + // } + + // if (data.tasks) { + + // let taskReport = {}; + + // createProject.tasks = await _projectTask( + // data.tasks + // ); + + // taskReport.total = createProject.tasks.length; + + // createProject.tasks.forEach(task => { + // if (!taskReport[task.status]) { + // taskReport[task.status] = 1; + // } else { + // taskReport[task.status] += 1; + // } + // }); + + // createProject["taskReport"] = taskReport; + // } + + // let booleanData = this.booleanData(schemas["projects"].schema); + // let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); + + + // Object.keys(data).forEach(updateData => { + // if ( + // !createProject[updateData] && + // projectsModel.includes(updateData) + // ) { + + // if (booleanData.includes(updateData)) { + + // createProject[updateData] = + // UTILS.convertStringToBoolean(data[updateData]); + + // } else if (mongooseIdData.includes(updateData)) { + // createProject[updateData] = ObjectId(data[updateData]); + // } else { + // createProject[updateData] = data[updateData]; + // } + // } + // }); + + // createProject["appInformation"] = {}; + // if (appName !== "") { + // createProject["appInformation"]["appName"] = appName; + // } + + // if (appVersion !== "") { + // createProject["appInformation"]["appVersion"] = appVersion; + // } + + // createProject["lastDownloadedAt"] = new Date(); + + // if (data.profileInformation) { + // createProject.userRoleInformation = data.profileInformation; + // } + + // createProject.status = UTILS.convertProjectStatus(data.status); + // let userProject = await projectQueries.createProject( + // createProject + // ); + + // await kafkaProducersHelper.pushProjectToKafka(userProject); + + // if (!userProject._id) { + // throw { + // message: CONSTANTS.apiResponses.USER_PROJECT_NOT_CREATED, + // status: HTTP_STATUS_CODE['bad_request'].status + // } + // } + + // return resolve({ + // success: true, + // message: CONSTANTS.apiResponses.PROJECT_CREATED, + // data: { + // programId: + // userProject.programInformation && userProject.programInformation._id ? + // userProject.programInformation._id : data.programId, + // projectId: userProject._id, + // lastDownloadedAt: userProject.lastDownloadedAt, + // hasAcceptedTAndC : userProject.hasAcceptedTAndC ? userProject.hasAcceptedTAndC : false + // } + // }); + } catch (error) { return resolve({ status: @@ -2479,25 +2633,42 @@ function _projectCategories(categories) { function _entitiesInformation(entityIds) { return new Promise(async (resolve, reject) => { try { - - let entityData = - await coreService.entityDocuments( - entityIds, - ["metaInformation", "entityType", "entityTypeId", "registryDetails"] - ); - - if (!entityData.success) { + let bodyData={}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = {}; + bodyData["request"]["filters"]["id"] = entityIds; + console.log(" bodyData inside recursive fn : ", bodyData["request"]["filters"]) + let entityDetails = await sunbirdService.learnerLocationSearch(bodyData); + console.log("entityDetails:",entityDetails) + let entities = entityDetails.data.response; + + if (!entities.length > 0) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND } } + let entityResult = []; + //formating response + entities.map(entityData => { + let data = {}; + data._id = entityData.id; + data.entityType = entityData.type; + data.metaInformation = {}; + data.metaInformation.name = entityData.name; + data.metaInformation.externalId = entityData.code + data.registryDetails = {}; + data.registryDetails.locationId = entityData.id; + data.registryDetails.code = entityData.code; + entityResult.push(data); + }); + console.log("entityResult : ",entityResult) let entitiesData = []; - if (entityData.success && entityData.data.length > 0) { + if ( entities.length > 0 ) { - entitiesData = _entitiesMetaInformation(entityData.data); + entitiesData = _entitiesMetaInformation(entityResult); } return resolve({ @@ -2505,6 +2676,31 @@ function _entitiesInformation(entityIds) { data: entitiesData }); + // let entityData = + // await coreService.entityDocuments( + // entityIds, + // ["metaInformation", "entityType", "entityTypeId", "registryDetails"] + // ); + + // if (!entityData.success) { + // throw { + // status: HTTP_STATUS_CODE['bad_request'].status, + // message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND + // } + // } + // console.log("entity data before: ",entityData) + // let entitiesData = []; + + // if (entityData.success && entityData.data.length > 0) { + + // entitiesData = _entitiesMetaInformation(entityData.data); + // } + + // return resolve({ + // success: true, + // data: entitiesData + // }); + } catch (error) { return resolve({ status: @@ -2768,13 +2964,20 @@ function _observationDetails(observationData, userRoleAndProfileInformation = {} function _entitiesMetaInformation(entitiesData) { entitiesData = entitiesData.map(entity => { - entity.metaInformation._id = ObjectId(entity._id); + entity.metaInformation._id = entity._id; entity.metaInformation.entityType = entity.entityType; - entity.metaInformation.entityTypeId = ObjectId(entity.entityTypeId); entity.metaInformation.registryDetails = entity.registryDetails; return entity.metaInformation; }); + // entitiesData = entitiesData.map(entity => { + // entity.metaInformation._id = ObjectId(entity._id); + // entity.metaInformation.entityType = entity.entityType; + // entity.metaInformation.entityTypeId = ObjectId(entity.entityTypeId); + // entity.metaInformation.registryDetails = entity.registryDetails; + // return entity.metaInformation; + // }); + console.log("entitiesData : ",entitiesData) return entitiesData; } From d5e8dfccda3a3be7b0074a1e6a0ac03d2975f2bd Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 21 Mar 2022 09:59:38 +0530 Subject: [PATCH 111/373] sunbird service --- generics/services/sunbird.js | 73 ++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 generics/services/sunbird.js diff --git a/generics/services/sunbird.js b/generics/services/sunbird.js new file mode 100644 index 00000000..d69ec39f --- /dev/null +++ b/generics/services/sunbird.js @@ -0,0 +1,73 @@ +/** + * name : sunbird.js + * author : Vishnudas + * Date : 16-March-2022 + * Description : All Sunbird learner related api call. + */ + +//dependencies + + +const request = require('request'); +const sunbirdBaseUrl = process.env.SUNBIRD_SERVICE_URL; + +/** + * + * @function + * @name learnerLocationSearch + * @param {String} bearerToken - autherization token. + * @param {object} bodyData - bodydata . + * @returns {Promise} returns a promise. +*/ + +const learnerLocationSearch = function ( bodyData ) { + return new Promise(async (resolve, reject) => { + try { + + const url = + sunbirdBaseUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; + const options = { + headers : { + "Authorization" : process.env.SUNBIRD_SERVICE_AUTHERIZATION, + "content-type": "application/json" + }, + json : bodyData + }; + + request.post(url,options,kendraCallback); + + function kendraCallback(err, data) { + + let result = { + success : true + }; + + if (err) { + result.success = false; + } else { + + let response = data.body; + + if( response.responseCode === CONSTANTS.common.OK) { + result["data"] = response.result; + } else { + result.success = false; + } + } + return resolve(result); + } + + setTimeout(function () { + return reject (CONSTANTS.common.TIMEOUT_ERROR) + }, CONSTANTS.common.SUNBIRD_SERVER_TIMEOUT); + + + } catch (error) { + return reject(error); + } + }) +} + +module.exports = { + learnerLocationSearch : learnerLocationSearch +}; \ No newline at end of file From 255003ef1163b8c69dd797e77f378eea444dff48 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 22 Mar 2022 22:21:08 +0530 Subject: [PATCH 112/373] entity generalization code march 22 2022 --- generics/services/sunbird.js | 7 +- module/reports/helper.js | 18 +-- module/userProjects/helper.js | 212 ++-------------------------------- 3 files changed, 20 insertions(+), 217 deletions(-) diff --git a/generics/services/sunbird.js b/generics/services/sunbird.js index d69ec39f..4006a779 100644 --- a/generics/services/sunbird.js +++ b/generics/services/sunbird.js @@ -16,14 +16,17 @@ const sunbirdBaseUrl = process.env.SUNBIRD_SERVICE_URL; * @function * @name learnerLocationSearch * @param {String} bearerToken - autherization token. - * @param {object} bodyData - bodydata . + * @param {object} filterData - bodydata . * @returns {Promise} returns a promise. */ -const learnerLocationSearch = function ( bodyData ) { +const learnerLocationSearch = function ( filterData ) { return new Promise(async (resolve, reject) => { try { + let bodyData={}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = filterData; const url = sunbirdBaseUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; const options = { diff --git a/module/reports/helper.js b/module/reports/helper.js index aedd3109..5a800d60 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -39,18 +39,13 @@ module.exports = class ReportsHelper { try { let query = { }; - //eG code + if (entityId) { query["entityId"] = entityId; } else { query["userId"] = userId } - // if (entityId) { - // query["entityId"] = ObjectId(entityId); - // } else { - // query["userId"] = userId - // } let dateRange = await _getDateRangeofReport(reportType); let endOf = dateRange.endOf; @@ -71,14 +66,14 @@ module.exports = class ReportsHelper { { "syncedAt": { $gte: new Date(startFrom), $lte: new Date(endOf) } }, { "tasks": { $elemMatch: { isDeleted: { $ne: true },syncedAt: { $gte: new Date(startFrom), $lte: new Date(endOf) } } } }, ] - console.log("Query : ",query) + const projectDetails = await projectQueries.projectDocument( query, ["programId","programInformation.name", "entityInformation.name", "taskReport", "status", "tasks", "categories"], [] ); - console.log("projectDetails : ",projectDetails) + let tasksReport = { "total": 0, "overdue": 0 @@ -498,12 +493,7 @@ module.exports = class ReportsHelper { query["userId"] = userId } - // if (entityId) { - // query["entityId"] = ObjectId(entityId); - // } else { - // query["userId"] = userId - // } - + let chartObject = []; let dateRange = await _getDateRangeofReport(reportType); let endOf = dateRange.endOf; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6b1779df..c00152cb 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -177,7 +177,7 @@ module.exports = class UserProjectsHelper { let addOrUpdateEntityToProject = false; if (data.entityId) { - console.log("#####here") + // If entity is not present in project or new entity is updated. if ( !userProject[0].entityInformation || @@ -189,7 +189,7 @@ module.exports = class UserProjectsHelper { addOrUpdateEntityToProject = true; } } - console.log(" addOrUpdateEntityToProject : ", addOrUpdateEntityToProject) + if (addOrUpdateEntityToProject) { let entityInformation = @@ -202,7 +202,7 @@ module.exports = class UserProjectsHelper { updateProject["entityInformation"] = entityInformation.data[0]; updateProject.entityId = entityInformation.data[0]._id; } - console.log("updateProject.entityId : ",updateProject.entityId ) + if (createNewProgramAndSolution || solutionExists) { let programAndSolutionInformation = @@ -913,7 +913,6 @@ module.exports = class UserProjectsHelper { "projectTemplateId" ] ); - console.log("project details : ",project) if (!project.length > 0) { throw { status: HTTP_STATUS_CODE['bad_request'].status, @@ -1503,161 +1502,6 @@ module.exports = class UserProjectsHelper { hasAcceptedTAndC : userProject.hasAcceptedTAndC ? userProject.hasAcceptedTAndC : false } }); - - // const projectsModel = Object.keys(schemas["projects"].schema); - // let createProject = {}; - - // createProject["userId"] = createProject["createdBy"] = createProject["updatedBy"] = userId; - - // let projectData = await _projectData(data); - // if (projectData && projectData.success == true) { - // createProject = _.merge(createProject, projectData.data); - // } - - // let createNewProgramAndSolution = false; - - // if (data.programId && data.programId !== "") { - // createNewProgramAndSolution = false; - // } - // else if (data.programName) { - // createNewProgramAndSolution = true; - // } - - // if (data.entityId) { - // let entityInformation = - // await _entitiesInformation([data.entityId]); - - // if (!entityInformation.success) { - // return resolve(entityInformation); - // } - - // createProject["entityInformation"] = entityInformation.data[0]; - // createProject.entityId = entityInformation.data[0]._id; - // } - // if (createNewProgramAndSolution) { - - // let programAndSolutionInformation = - // await this.createProgramAndSolution( - // data.programId, - // data.programName, - // createProject.entityId ? [createProject.entityId] : "", - // userToken - // ); - - // if (!programAndSolutionInformation.success) { - // return resolve(programAndSolutionInformation); - // } - // createProject = - // _.merge(createProject, programAndSolutionInformation.data); - // } else { - // let queryData = {}; - // queryData["_id"] = data.programId; - // let programDetails = await programsQueries.programsDocument(queryData, - // [ - // "_id", - // "name", - // "description", - // "isAPrivateProgram" - // ] - // ); - // if( !programDetails.length > 0 ){ - // throw { - // status: HTTP_STATUS_CODE['bad_request'].status, - // message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND - // }; - // } - // let programInformationData = {}; - // programInformationData["programInformation"] = programDetails[0]; - // createProject = - // _.merge(createProject, programInformationData); - // } - - // if (data.tasks) { - - // let taskReport = {}; - - // createProject.tasks = await _projectTask( - // data.tasks - // ); - - // taskReport.total = createProject.tasks.length; - - // createProject.tasks.forEach(task => { - // if (!taskReport[task.status]) { - // taskReport[task.status] = 1; - // } else { - // taskReport[task.status] += 1; - // } - // }); - - // createProject["taskReport"] = taskReport; - // } - - // let booleanData = this.booleanData(schemas["projects"].schema); - // let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); - - - // Object.keys(data).forEach(updateData => { - // if ( - // !createProject[updateData] && - // projectsModel.includes(updateData) - // ) { - - // if (booleanData.includes(updateData)) { - - // createProject[updateData] = - // UTILS.convertStringToBoolean(data[updateData]); - - // } else if (mongooseIdData.includes(updateData)) { - // createProject[updateData] = ObjectId(data[updateData]); - // } else { - // createProject[updateData] = data[updateData]; - // } - // } - // }); - - // createProject["appInformation"] = {}; - // if (appName !== "") { - // createProject["appInformation"]["appName"] = appName; - // } - - // if (appVersion !== "") { - // createProject["appInformation"]["appVersion"] = appVersion; - // } - - // createProject["lastDownloadedAt"] = new Date(); - - // if (data.profileInformation) { - // createProject.userRoleInformation = data.profileInformation; - // } - - // createProject.status = UTILS.convertProjectStatus(data.status); - // let userProject = await projectQueries.createProject( - // createProject - // ); - - // await kafkaProducersHelper.pushProjectToKafka(userProject); - - // if (!userProject._id) { - // throw { - // message: CONSTANTS.apiResponses.USER_PROJECT_NOT_CREATED, - // status: HTTP_STATUS_CODE['bad_request'].status - // } - // } - - // return resolve({ - // success: true, - // message: CONSTANTS.apiResponses.PROJECT_CREATED, - // data: { - // programId: - // userProject.programInformation && userProject.programInformation._id ? - // userProject.programInformation._id : data.programId, - // projectId: userProject._id, - // lastDownloadedAt: userProject.lastDownloadedAt, - // hasAcceptedTAndC : userProject.hasAcceptedTAndC ? userProject.hasAcceptedTAndC : false - // } - // }); - } catch (error) { return resolve({ status: @@ -2633,13 +2477,13 @@ function _projectCategories(categories) { function _entitiesInformation(entityIds) { return new Promise(async (resolve, reject) => { try { - let bodyData={}; - bodyData["request"] = {}; - bodyData["request"]["filters"] = {}; - bodyData["request"]["filters"]["id"] = entityIds; - console.log(" bodyData inside recursive fn : ", bodyData["request"]["filters"]) + let bodyData={ + "id" : entityIds + }; + + let entityDetails = await sunbirdService.learnerLocationSearch(bodyData); - console.log("entityDetails:",entityDetails) + let entities = entityDetails.data.response; if (!entities.length > 0) { @@ -2662,7 +2506,7 @@ function _entitiesInformation(entityIds) { data.registryDetails.code = entityData.code; entityResult.push(data); }); - console.log("entityResult : ",entityResult) + let entitiesData = []; @@ -2676,31 +2520,6 @@ function _entitiesInformation(entityIds) { data: entitiesData }); - // let entityData = - // await coreService.entityDocuments( - // entityIds, - // ["metaInformation", "entityType", "entityTypeId", "registryDetails"] - // ); - - // if (!entityData.success) { - // throw { - // status: HTTP_STATUS_CODE['bad_request'].status, - // message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND - // } - // } - // console.log("entity data before: ",entityData) - // let entitiesData = []; - - // if (entityData.success && entityData.data.length > 0) { - - // entitiesData = _entitiesMetaInformation(entityData.data); - // } - - // return resolve({ - // success: true, - // data: entitiesData - // }); - } catch (error) { return resolve({ status: @@ -2968,16 +2787,7 @@ function _entitiesMetaInformation(entitiesData) { entity.metaInformation.entityType = entity.entityType; entity.metaInformation.registryDetails = entity.registryDetails; return entity.metaInformation; - }); - - // entitiesData = entitiesData.map(entity => { - // entity.metaInformation._id = ObjectId(entity._id); - // entity.metaInformation.entityType = entity.entityType; - // entity.metaInformation.entityTypeId = ObjectId(entity.entityTypeId); - // entity.metaInformation.registryDetails = entity.registryDetails; - // return entity.metaInformation; - // }); - console.log("entitiesData : ",entitiesData) + }); return entitiesData; } From 3607a15721f566e021da61592bae70d49e742075 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 23 Mar 2022 18:10:43 +0530 Subject: [PATCH 113/373] resolves lvl1 --- generics/constants/common.js | 1 - generics/services/sunbird.js | 16 +++++++++------- module/userProjects/helper.js | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index 8b72cbe7..04d18daa 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -46,6 +46,5 @@ module.exports = { "PROJECT_ATTACHMENT" : "project", "TASK_ATTACHMENT" : "task", "SUNBIRD_SERVER_TIMEOUT" : 5000, - "TIMEOUT_ERROR" : "Server timeout error", "OK" : "OK" }; diff --git a/generics/services/sunbird.js b/generics/services/sunbird.js index 4006a779..3919f1fb 100644 --- a/generics/services/sunbird.js +++ b/generics/services/sunbird.js @@ -16,7 +16,7 @@ const sunbirdBaseUrl = process.env.SUNBIRD_SERVICE_URL; * @function * @name learnerLocationSearch * @param {String} bearerToken - autherization token. - * @param {object} filterData - bodydata . + * @param {object} bodyData - bodydata . * @returns {Promise} returns a promise. */ @@ -39,12 +39,13 @@ const learnerLocationSearch = function ( filterData ) { request.post(url,options,kendraCallback); - function kendraCallback(err, data) { + let result = { + success : true + }; - let result = { - success : true - }; + function kendraCallback(err, data) { + if (err) { result.success = false; } else { @@ -61,10 +62,11 @@ const learnerLocationSearch = function ( filterData ) { } setTimeout(function () { - return reject (CONSTANTS.common.TIMEOUT_ERROR) + return reject (result = { + success : false + }); }, CONSTANTS.common.SUNBIRD_SERVER_TIMEOUT); - } catch (error) { return reject(error); } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c00152cb..aa77d44a 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2483,15 +2483,15 @@ function _entitiesInformation(entityIds) { let entityDetails = await sunbirdService.learnerLocationSearch(bodyData); - - let entities = entityDetails.data.response; - if (!entities.length > 0) { + if (!entityDetails.success || !entityDetails.data.response.length > 0) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND } } + + let entities = entityDetails.data.response; let entityResult = []; //formating response entities.map(entityData => { From c2c63cde6c3926ed4d00c338152a58ac8fa98ac9 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 24 Mar 2022 13:37:07 +0530 Subject: [PATCH 114/373] 4.7 hotfix --- models/project-template-tasks.js | 3 ++- models/project-templates.js | 3 ++- models/projects.js | 13 ++++++++++--- module/library/categories/helper.js | 2 +- module/userProjects/helper.js | 10 +++++----- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/models/project-template-tasks.js b/models/project-template-tasks.js index d2d14db6..bdfb20bd 100644 --- a/models/project-template-tasks.js +++ b/models/project-template-tasks.js @@ -25,7 +25,8 @@ module.exports = { }, isDeleted : { type : Boolean, - default : false + default : false, + index: true }, externalId : { type : String, diff --git a/models/project-templates.js b/models/project-templates.js index 45d1604e..af68a5fe 100644 --- a/models/project-templates.js +++ b/models/project-templates.js @@ -45,7 +45,8 @@ module.exports = { }, isDeleted : { type : Boolean, - default : false + default : false, + index : true }, recommendedFor : { type : Array, diff --git a/models/projects.js b/models/projects.js index bfca077a..fc0a8827 100644 --- a/models/projects.js +++ b/models/projects.js @@ -8,8 +8,14 @@ module.exports = { name: "projects", schema: { - title : String, - description : String, + title : { + type : String, + index: true + }, + description : { + type : String, + index: true + }, taskReport : { type : Object, default : {} @@ -46,7 +52,8 @@ module.exports = { }, createdBy : { type : String, - default : "SYSTEM" + default : "SYSTEM", + index: true }, tasks : { type : Array, diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index dd732aa4..67828b8d 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -211,7 +211,7 @@ module.exports = class LibraryCategoriesHelper { isDeleted : false }); - if( tasks && tasks.length > 0 ) { + if( tasks && tasks.length > 0 ) { let taskData = {}; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 8789d5fa..af14a7be 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1698,12 +1698,12 @@ module.exports = class UserProjectsHelper { if ( filter && filter !== "" ) { if( filter === CONSTANTS.common.CREATED_BY_ME ) { - query["isAPrivateProgram"] = { - $ne : false - }; query["referenceFrom"] = { $ne : CONSTANTS.common.LINK }; + query["isAPrivateProgram"] = { + $ne : false + }; } else if( filter == CONSTANTS.common.ASSIGN_TO_ME ) { query["isAPrivateProgram"] = false; } else{ @@ -1733,7 +1733,7 @@ module.exports = class UserProjectsHelper { let totalCount = 0; let data = []; - if( projects.success && projects.data ) { + if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { totalCount = projects.data.count; data = projects.data.data; @@ -1742,6 +1742,7 @@ module.exports = class UserProjectsHelper { data.forEach( projectData => { projectData.name = projectData.title; + if (projectData.programInformation) { projectData.programName = projectData.programInformation.name; delete projectData.programInformation; @@ -1753,7 +1754,6 @@ module.exports = class UserProjectsHelper { } projectData.type = CONSTANTS.common.IMPROVEMENT_PROJECT; - delete projectData.title; }); } From dcb950bde361d5eedd5ca43ee091e7ff77eda169 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 25 Mar 2022 12:52:05 +0530 Subject: [PATCH 115/373] userProfile from observation --- controllers/v1/observations.js | 15 ++++++++ databaseQueries/observations.js | 62 +++++++++++++++++++++++++++++++++ models/observations.js | 58 ++++++++++++++++++++++++++++++ models/programs.js | 1 - module/userProjects/helper.js | 27 ++++++++++++++ 5 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 controllers/v1/observations.js create mode 100644 databaseQueries/observations.js create mode 100644 models/observations.js diff --git a/controllers/v1/observations.js b/controllers/v1/observations.js new file mode 100644 index 00000000..d3f87f52 --- /dev/null +++ b/controllers/v1/observations.js @@ -0,0 +1,15 @@ +/** + * name : observations.js + * author : Priyanka Pradeep + * created-date : 25-Mar-2022 + * Description : observation related information. + */ +module.exports = class Observations extends Abstract{ + constructor() { + super("observations"); + } + + static get name() { + return "observations"; + } +} \ No newline at end of file diff --git a/databaseQueries/observations.js b/databaseQueries/observations.js new file mode 100644 index 00000000..b0a4e862 --- /dev/null +++ b/databaseQueries/observations.js @@ -0,0 +1,62 @@ +/** + * name : observations.js + * author : Priyanka Pradeep + * created-date : 25-Mar-2022 + * Description : Observation helper for DB interactions. + */ + +// Dependencies + +/** + * Observations + * @class +*/ + + + +module.exports= class Observations{ + /** + * Observation details. + * @method + * @name observationDocument + * @param {Array} [filterData = "all"] - solutions filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} solutions details. + */ + + static observationDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + let observationDoc = + await database.models.observations.find( + queryObject, + projection + ).lean(); + + return resolve(observationDoc); + + } catch (error) { + return reject(error); + } + }); + } +} \ No newline at end of file diff --git a/models/observations.js b/models/observations.js new file mode 100644 index 00000000..a105286e --- /dev/null +++ b/models/observations.js @@ -0,0 +1,58 @@ +module.exports = { + name: "observations", + schema: { + name: String, + description: String, + createdBy: { + type : String, + index : true + }, + frameworkId: "ObjectId", + frameworkExternalId: String, + solutionId: { + type : "ObjectId", + index : true + }, + programId: { + type: "ObjectId", + required: true, + index : true + }, + programExternalId: { + type: String, + required: true, + index : true + }, + solutionExternalId: { + type : String, + index : true + }, + startDate: Date, + endDate: Date, + status: { + type : String, + index : true + }, + entityTypeId: { + type : "ObjectId", + index : true + }, + entityType : String, + entities: Array, + isAPrivateProgram : { + default : false, + type : Boolean, + index: true + }, + link: { + type: String, + index: true + }, + project : Object, + referenceFrom : { + type: String, + index: true + }, + userRoleInformation : Object + } +}; \ No newline at end of file diff --git a/models/programs.js b/models/programs.js index 2e934c54..67b6a227 100644 --- a/models/programs.js +++ b/models/programs.js @@ -23,7 +23,6 @@ module.exports = { concepts: ["json"], imageCompression: {}, components: ["json"], - components: ["json"], isAPrivateProgram : { default : false, type : Boolean diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index d06fab0f..13971217 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,6 +21,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); +const observationQueries = require(DB_QUERY_BASE_PATH + "/observations"); /** * UserProjectsHelper @@ -1080,6 +1081,7 @@ module.exports = class UserProjectsHelper { solutionDetails = solutionDetails.data; } else { + solutionDetails = await surveyService.listSolutions([solutionExternalId]); if( !solutionDetails.success ) { @@ -1147,6 +1149,8 @@ module.exports = class UserProjectsHelper { if( appVersion !== "" ) { projectCreation.data["appInformation"]["appVersion"] = appVersion; } + + let getUserProfileFromObservation = false; if( bodyData && Object.keys(bodyData).length > 0 ) { @@ -1158,6 +1162,9 @@ module.exports = class UserProjectsHelper { projectCreation.data.referenceFrom = bodyData.referenceFrom; if( bodyData.submissions ) { + if ( bodyData.submissions.observationId && bodyData.submissions.observationId != "" ) { + getUserProfileFromObservation = true; + } projectCreation.data.submissions = bodyData.submissions; } } @@ -1190,6 +1197,26 @@ module.exports = class UserProjectsHelper { projectCreation.data.status = CONSTANTS.common.STARTED; projectCreation.data.lastDownloadedAt = new Date(); + + // fetch userRoleInformation from observation if referenecFrom is observation + if ( getUserProfileFromObservation ){ + + let observationDocument = await observationQueries.observationDocument({ + _id: bodyData.submissions.observationId + }, + [ + "userRoleInformation" + ]); + + if( observationDocument.length > 0 && + observationDocument[0].userRoleInformation && + Object.keys(observationDocument[0].userRoleInformation).length > 0 + ) { + + userRoleInformation = observationDocument[0].userRoleInformation; + } + } + projectCreation.data.userRoleInformation = userRoleInformation; let project = await projectQueries.createProject(projectCreation.data); From 347538312a4ecc1ba88918f6ac8b2991b2689291 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 25 Mar 2022 13:47:41 +0530 Subject: [PATCH 116/373] Pr changes --- controllers/v1/observations.js | 15 --------- generics/constants/endpoints.js | 3 +- generics/services/survey.js | 7 ++-- models/observations.js | 58 --------------------------------- module/userProjects/helper.js | 24 +++++++------- 5 files changed, 17 insertions(+), 90 deletions(-) delete mode 100644 controllers/v1/observations.js delete mode 100644 models/observations.js diff --git a/controllers/v1/observations.js b/controllers/v1/observations.js deleted file mode 100644 index d3f87f52..00000000 --- a/controllers/v1/observations.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * name : observations.js - * author : Priyanka Pradeep - * created-date : 25-Mar-2022 - * Description : observation related information. - */ -module.exports = class Observations extends Abstract{ - constructor() { - super("observations"); - } - - static get name() { - return "observations"; - } -} \ No newline at end of file diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 4a249318..45a88a26 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -44,5 +44,6 @@ module.exports = { LIST_ENTITIES_BY_LOCATION_IDS : "/v1/entities/listByLocationIds", CREATE_IMPROVEMENT_PROJECT_SOLUTION : "/v1/solutions/create", PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport", - FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl" + FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl", + OBSERVATION_DETAILS : "/v1/observations/details" }; diff --git a/generics/services/survey.js b/generics/services/survey.js index 76a6f43f..e15f5c07 100644 --- a/generics/services/survey.js +++ b/generics/services/survey.js @@ -319,7 +319,7 @@ const observationDetails = function (token,observationId) { let url = ASSESSMENT_URL + CONSTANTS.endpoints.OBSERVATION_DETAILS + "/" + observationId; - + const options = { headers : { "content-type": "application/json", @@ -340,7 +340,7 @@ const observationDetails = function (token,observationId) { result.success = false; } else { - let response = data.body; + let response = JSON.parse(data.body); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { @@ -348,6 +348,7 @@ const observationDetails = function (token,observationId) { } } + return resolve(result); } @@ -388,7 +389,7 @@ const listSolutions = function (solutionIds) { let result = { success : true }; - + if (err) { result.success = false; } else { diff --git a/models/observations.js b/models/observations.js deleted file mode 100644 index a105286e..00000000 --- a/models/observations.js +++ /dev/null @@ -1,58 +0,0 @@ -module.exports = { - name: "observations", - schema: { - name: String, - description: String, - createdBy: { - type : String, - index : true - }, - frameworkId: "ObjectId", - frameworkExternalId: String, - solutionId: { - type : "ObjectId", - index : true - }, - programId: { - type: "ObjectId", - required: true, - index : true - }, - programExternalId: { - type: String, - required: true, - index : true - }, - solutionExternalId: { - type : String, - index : true - }, - startDate: Date, - endDate: Date, - status: { - type : String, - index : true - }, - entityTypeId: { - type : "ObjectId", - index : true - }, - entityType : String, - entities: Array, - isAPrivateProgram : { - default : false, - type : Boolean, - index: true - }, - link: { - type: String, - index: true - }, - project : Object, - referenceFrom : { - type: String, - index: true - }, - userRoleInformation : Object - } -}; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 13971217..93bce04f 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,7 +21,6 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); -const observationQueries = require(DB_QUERY_BASE_PATH + "/observations"); /** * UserProjectsHelper @@ -1201,19 +1200,18 @@ module.exports = class UserProjectsHelper { // fetch userRoleInformation from observation if referenecFrom is observation if ( getUserProfileFromObservation ){ - let observationDocument = await observationQueries.observationDocument({ - _id: bodyData.submissions.observationId - }, - [ - "userRoleInformation" - ]); - - if( observationDocument.length > 0 && - observationDocument[0].userRoleInformation && - Object.keys(observationDocument[0].userRoleInformation).length > 0 - ) { + let observationDetails = await surveyService.observationDetails( + userToken, + bodyData.submissions.observationId + ); + + if( observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userRoleInformation && + Object.keys(observationDetails.data.userRoleInformation).length > 0 + ) { - userRoleInformation = observationDocument[0].userRoleInformation; + userRoleInformation = observationDetails.data.userRoleInformation; } } From 2fcb09f08e3eebe20d906c8834b27c083198d191 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 25 Mar 2022 13:49:12 +0530 Subject: [PATCH 117/373] PR changes --- databaseQueries/observations.js | 62 --------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 databaseQueries/observations.js diff --git a/databaseQueries/observations.js b/databaseQueries/observations.js deleted file mode 100644 index b0a4e862..00000000 --- a/databaseQueries/observations.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * name : observations.js - * author : Priyanka Pradeep - * created-date : 25-Mar-2022 - * Description : Observation helper for DB interactions. - */ - -// Dependencies - -/** - * Observations - * @class -*/ - - - -module.exports= class Observations{ - /** - * Observation details. - * @method - * @name observationDocument - * @param {Array} [filterData = "all"] - solutions filter query. - * @param {Array} [fieldsArray = "all"] - projected fields. - * @param {Array} [skipFields = "none"] - field not to include - * @returns {Array} solutions details. - */ - - static observationDocument( - filterData = "all", - fieldsArray = "all", - skipFields = "none" - ) { - return new Promise(async (resolve, reject) => { - try { - let queryObject = (filterData != "all") ? filterData : {}; - let projection = {} - - if (fieldsArray != "all") { - fieldsArray.forEach(field => { - projection[field] = 1; - }); - } - - if( skipFields !== "none" ) { - skipFields.forEach(field=>{ - projection[field] = 0; - }); - } - let observationDoc = - await database.models.observations.find( - queryObject, - projection - ).lean(); - - return resolve(observationDoc); - - } catch (error) { - return reject(error); - } - }); - } -} \ No newline at end of file From f8938378ad4fe092102f488ea819c35d0eb9eb27 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 29 Mar 2022 09:48:30 +0530 Subject: [PATCH 118/373] edit in sunbirdservice --- generics/services/sunbird.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generics/services/sunbird.js b/generics/services/sunbird.js index 3919f1fb..acb324cf 100644 --- a/generics/services/sunbird.js +++ b/generics/services/sunbird.js @@ -37,13 +37,13 @@ const learnerLocationSearch = function ( filterData ) { json : bodyData }; - request.post(url,options,kendraCallback); + request.post(url,options,learnerSearchCallback); let result = { success : true }; - function kendraCallback(err, data) { + function learnerSearchCallback(err, data) { if (err) { From 30e7001753dee0073405386e34afaa8ccca985a1 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 30 Mar 2022 16:30:54 +0530 Subject: [PATCH 119/373] env and data check added --- envVariables.js | 4 ++++ generics/constants/common.js | 1 - generics/services/sunbird.js | 4 ++-- module/userProjects/helper.js | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/envVariables.js b/envVariables.js index a1600dab..f3f893f5 100644 --- a/envVariables.js +++ b/envVariables.js @@ -35,6 +35,10 @@ let enviromentVariables = { "KAFKA_URL" : { "message" : "Required", "optional" : false + }, + "SUNBIRD_SERVICE_URL" : { + "message" : "Required sunbird service url", + "optional" : false } } diff --git a/generics/constants/common.js b/generics/constants/common.js index 04d18daa..23a7f786 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -45,6 +45,5 @@ module.exports = { "ATTACHMENT_TYPE_LINK" : "link", "PROJECT_ATTACHMENT" : "project", "TASK_ATTACHMENT" : "task", - "SUNBIRD_SERVER_TIMEOUT" : 5000, "OK" : "OK" }; diff --git a/generics/services/sunbird.js b/generics/services/sunbird.js index acb324cf..4ca73220 100644 --- a/generics/services/sunbird.js +++ b/generics/services/sunbird.js @@ -10,7 +10,7 @@ const request = require('request'); const sunbirdBaseUrl = process.env.SUNBIRD_SERVICE_URL; - +const serverTimeout = process.env.SUNBIRD_SERVER_TIMEOUT ? parseInt( process.env.SUNBIRD_SERVER_TIMEOUT ) : 5000; /** * * @function @@ -65,7 +65,7 @@ const learnerLocationSearch = function ( filterData ) { return reject (result = { success : false }); - }, CONSTANTS.common.SUNBIRD_SERVER_TIMEOUT); + }, serverTimeout); } catch (error) { return reject(error); diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index aa77d44a..2a3170b7 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2484,7 +2484,7 @@ function _entitiesInformation(entityIds) { let entityDetails = await sunbirdService.learnerLocationSearch(bodyData); - if (!entityDetails.success || !entityDetails.data.response.length > 0) { + if (!entityDetails.success || !entityDetails.data || !entityDetails.data.response.length > 0) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND From 9abd928a9302c4da35b9381db7cf9eab4e251815 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Mon, 4 Apr 2022 19:30:58 +0530 Subject: [PATCH 120/373] Remove duplicate for constants. --- module/userProjects/helper.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 0bbac27d..67aaa403 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -18,9 +18,6 @@ const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); - -const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); - const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); From 25fa721c710345362c8be026e9d394770b575ca5 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 18 Apr 2022 10:52:51 +0530 Subject: [PATCH 121/373] model change --- models/projects.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/projects.js b/models/projects.js index 597b8d2d..72e67ea2 100644 --- a/models/projects.js +++ b/models/projects.js @@ -134,6 +134,7 @@ module.exports = { type : Array, default : [] }, - remarks : String + remarks : String, + userProfile : Object } }; From f93de2a4d5b9bf21382f0302bd865597efbdc8bf Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 18 Apr 2022 11:22:32 +0530 Subject: [PATCH 122/373] user profile added --- envVariables.js | 4 ++ generics/constants/endpoints.js | 3 +- generics/http-status-codes/index.js | 3 +- generics/services/users.js | 66 +++++++++++++++++++++++++++++ module/userProjects/helper.js | 36 +++++++++++++++- 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 generics/services/users.js diff --git a/envVariables.js b/envVariables.js index a1600dab..9ccd9f9f 100644 --- a/envVariables.js +++ b/envVariables.js @@ -35,6 +35,10 @@ let enviromentVariables = { "KAFKA_URL" : { "message" : "Required", "optional" : false + }, + "USER_SERVICE_URL" : { + "message" : "Required user service base url", + "optional" : false } } diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 45a88a26..385ffd15 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -45,5 +45,6 @@ module.exports = { CREATE_IMPROVEMENT_PROJECT_SOLUTION : "/v1/solutions/create", PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport", FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl", - OBSERVATION_DETAILS : "/v1/observations/details" + OBSERVATION_DETAILS : "/v1/observations/details", + USER_READ_V5 : "/v5/user/read" }; diff --git a/generics/http-status-codes/index.js b/generics/http-status-codes/index.js index e105035f..f673f7d8 100644 --- a/generics/http-status-codes/index.js +++ b/generics/http-status-codes/index.js @@ -16,7 +16,8 @@ module.exports = { }, 'ok': { status: 200, - message: "Success" + message: "Success", + code: "OK" }, 'created': { status: 201, diff --git a/generics/services/users.js b/generics/services/users.js new file mode 100644 index 00000000..59684ea5 --- /dev/null +++ b/generics/services/users.js @@ -0,0 +1,66 @@ +/** + * name : users.js + * author : Vishnu + * Date : 07-April-2022 + * Description : All users related api call. + */ + +//dependencies +const request = require('request'); +const userServiceUrl = process.env.USER_SERVICE_URL; +const serverTimeout = process.env.SUNBIRD_SERVER_TIMEOUT ? parseInt(process.env.SUNBIRD_SERVER_TIMEOUT) : 5000; + +const profile = function ( token,userId = "" ) { + return new Promise(async (resolve, reject) => { + try { + + let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_V5; + + if( userId !== "" ) { + url = url + "/" + userId + "?" + "fields=organisations,roles,locations,declarations,externalIds" + } + + const options = { + headers : { + "content-type": "application/json", + "x-authenticated-user-token" : token, + "Authorization" : "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJSbTBGOTlnMnd4SmZKelJwa2YzTnRlaE5CYlJnZXRCaCJ9.CjDN6GufxylpAM5J_6j9fD0wq7S2qr1F6FOzAZtQ6XU" + } + }; + + request.get(url,options,userReadCallback); + let result = { + success : true + }; + function userReadCallback(err, data) { + + if (err) { + result.success = false; + } else { + + let response = JSON.parse(data.body); + if( response.responseCode === HTTP_STATUS_CODE['ok'].code ) { + result["data"] = response.result; + } else { + result.success = false; + } + + } + console.log("result : ",result.data.response) + return resolve(result); + } + setTimeout(function () { + return reject (result = { + success : false + }); + }, serverTimeout); + + } catch (error) { + return reject(error); + } + }) +} + +module.exports = { + profile : profile +} diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 93bce04f..fb47aedf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,6 +21,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); +const sunbirdUserProfile = require(GENERICS_FILES_PATH + "/services/users"); /** * UserProjectsHelper @@ -1196,7 +1197,7 @@ module.exports = class UserProjectsHelper { projectCreation.data.status = CONSTANTS.common.STARTED; projectCreation.data.lastDownloadedAt = new Date(); - + // fetch userRoleInformation from observation if referenecFrom is observation if ( getUserProfileFromObservation ){ @@ -1212,6 +1213,27 @@ module.exports = class UserProjectsHelper { ) { userRoleInformation = observationDetails.data.userRoleInformation; + + } + + if( observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userProfile && + Object.keys(observationDetails.data.userProfile).length > 0 + ) { + + projectCreation.data.userProfile = observationDetails.data.userProfile; + + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfile = await sunbirdUserProfile.profile(userToken, userId); + if ( userProfile.success && + userProfile.data && + userProfile.data.response + ) { + createProject.userProfile = userProfile.data.response; + } } } @@ -1382,6 +1404,18 @@ module.exports = class UserProjectsHelper { createProject["userId"] = createProject["createdBy"] = createProject["updatedBy"] = userId; + //Fetch user profile information by calling sunbird's user read api. + + let userProfile = await sunbirdUserProfile.profile(userToken, userId); + if ( userProfile.success && + userProfile.data && + userProfile.data.response + ) { + createProject.userProfile = userProfile.data.response; + } + + + let projectData = await _projectData(data); if (projectData && projectData.success == true) { createProject = _.merge(createProject, projectData.data); From 37b2e119590511829340c97852d623a9b46f2316 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 18 Apr 2022 11:25:08 +0530 Subject: [PATCH 123/373] remove console --- generics/services/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/services/users.js b/generics/services/users.js index 59684ea5..ec3c58d2 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -46,7 +46,7 @@ const profile = function ( token,userId = "" ) { } } - console.log("result : ",result.data.response) + return resolve(result); } setTimeout(function () { From 723bcaba8fa31b71db0d01d8e81456f52c05523b Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 18 Apr 2022 11:30:07 +0530 Subject: [PATCH 124/373] removed auth --- generics/services/users.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/generics/services/users.js b/generics/services/users.js index ec3c58d2..f4c1dc94 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -23,8 +23,7 @@ const profile = function ( token,userId = "" ) { const options = { headers : { "content-type": "application/json", - "x-authenticated-user-token" : token, - "Authorization" : "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJSbTBGOTlnMnd4SmZKelJwa2YzTnRlaE5CYlJnZXRCaCJ9.CjDN6GufxylpAM5J_6j9fD0wq7S2qr1F6FOzAZtQ6XU" + "x-authenticated-user-token" : token } }; From 57f02ce141145a94ae5908fc749114a86770127f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 18 Apr 2022 12:32:33 +0530 Subject: [PATCH 125/373] importFromLibrary add userProfile --- module/userProjects/helper.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index fb47aedf..c6878686 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1956,8 +1956,9 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, status: HTTP_STATUS_CODE['bad_request'].status }; + } - + let taskReport = {}; if ( @@ -2053,7 +2054,16 @@ module.exports = class UserProjectsHelper { ) } + //Fetch user profile information by calling sunbird's user read api. + let userProfile = await sunbirdUserProfile.profile(userToken, userId); + if ( userProfile.success && + userProfile.data && + userProfile.data.response + ) { + libraryProjects.data.userProfile = userProfile.data.response; + } + libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; libraryProjects.data.lastDownloadedAt = new Date(); libraryProjects.data.status = CONSTANTS.common.STARTED; From fe8e513a49530ee5f2f87b16f2c1b2497804f939 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 19 Apr 2022 12:05:04 +0530 Subject: [PATCH 126/373] update report Information in solutions --- databaseQueries/solutions.js | 47 ++++++++++++++ generics/constants/common.js | 3 +- models/solutions.js | 3 +- module/userProjects/helper.js | 115 +++++++++++++++++++++++++++++++++- 4 files changed, 164 insertions(+), 4 deletions(-) diff --git a/databaseQueries/solutions.js b/databaseQueries/solutions.js index c4cc635e..d8f87302 100644 --- a/databaseQueries/solutions.js +++ b/databaseQueries/solutions.js @@ -59,4 +59,51 @@ module.exports= class Solutions{ } }); } + + /** + * Update solution document. + * @method + * @name updateSolutionDocument + * @param {Object} query - query to find document + * @param {Object} updateObject - fields to update + * @returns {String} - message. + */ + + static updateSolutionDocument(query= {}, updateObject= {}) { + return new Promise(async (resolve, reject) => { + try { + + if (Object.keys(query).length == 0) { + throw new Error(messageConstants.apiResponses.UPDATE_QUERY_REQUIRED) + } + + if (Object.keys(updateObject).length == 0) { + throw new Error (messageConstants.apiResponses.UPDATE_OBJECT_REQUIRED) + } + + let updateResponse = await database.models.solutions.updateOne + ( + query, + updateObject + ) + + if (updateResponse.nModified == 0) { + throw new Error(CONSTANTS.apiResponses.FAILED_TO_UPDATE) + } + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, + data: true + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: false + }); + } + }); + } } \ No newline at end of file diff --git a/generics/constants/common.js b/generics/constants/common.js index 009bf7e9..237b396e 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -44,5 +44,6 @@ module.exports = { "CHILDREN" : "children", "ATTACHMENT_TYPE_LINK" : "link", "PROJECT_ATTACHMENT" : "project", - "TASK_ATTACHMENT" : "task" + "TASK_ATTACHMENT" : "task", + "DISTRICT": "district" }; diff --git a/models/solutions.js b/models/solutions.js index 511c5d4f..4e3c4c9f 100644 --- a/models/solutions.js +++ b/models/solutions.js @@ -97,6 +97,7 @@ module.exports = { minNoOfSubmissionsRequired: { type: Number, default: 1 - } + }, + reportInformation : Object } }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c6878686..6e806bd7 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -22,6 +22,7 @@ const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const sunbirdUserProfile = require(GENERICS_FILES_PATH + "/services/users"); +const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); /** * UserProjectsHelper @@ -1199,6 +1200,7 @@ module.exports = class UserProjectsHelper { projectCreation.data.lastDownloadedAt = new Date(); // fetch userRoleInformation from observation if referenecFrom is observation + let addReportInfoToSolution = false; if ( getUserProfileFromObservation ){ let observationDetails = await surveyService.observationDetails( @@ -1223,6 +1225,7 @@ module.exports = class UserProjectsHelper { ) { projectCreation.data.userProfile = observationDetails.data.userProfile; + addReportInfoToSolution = true; } else { //Fetch user profile information by calling sunbird's user read api. @@ -1232,7 +1235,8 @@ module.exports = class UserProjectsHelper { userProfile.data && userProfile.data.response ) { - createProject.userProfile = userProfile.data.response; + projectCreation.data.userProfile = userProfile.data.response; + addReportInfoToSolution = true; } } } @@ -1241,6 +1245,14 @@ module.exports = class UserProjectsHelper { let project = await projectQueries.createProject(projectCreation.data); + if ( addReportInfoToSolution && project.solutionId ) { + await _addReportInformationInSolution( + project._id, + project.solutionId, + project.userProfile + ); + } + await kafkaProducersHelper.pushProjectToKafka(project); projectId = project._id; @@ -2055,13 +2067,14 @@ module.exports = class UserProjectsHelper { } //Fetch user profile information by calling sunbird's user read api. - + let addReportInfoToSolution = false; let userProfile = await sunbirdUserProfile.profile(userToken, userId); if ( userProfile.success && userProfile.data && userProfile.data.response ) { libraryProjects.data.userProfile = userProfile.data.response; + addReportInfoToSolution = true; } libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; @@ -2082,6 +2095,15 @@ module.exports = class UserProjectsHelper { let projectCreation = await database.models.projects.create( _.omit(libraryProjects.data, ["_id"]) ); + + if ( addReportInfoToSolution && projectCreation._doc.solutionId ) { + + await _addReportInformationInSolution( + projectCreation._doc._id, + projectCreation._doc.solutionId, + projectCreation._doc.userProfile + ); + } await kafkaProducersHelper.pushProjectToKafka(projectCreation); @@ -2908,5 +2930,94 @@ function _projectData(data) { }) } +/** + * Entities information for project. + * @method + * @name _addReportInformationInSolution + * @param {String} entityIds - entity id. + * @returns {Object} Project entity information. +*/ + +function _addReportInformationInSolution(projectId, solutionId, userProfile = {}) { + return new Promise(async (resolve, reject) => { + try { + + let district = {}; + let organisation = []; + + for (const location of userProfile["userLocations"]) { + if ( location.type == CONSTANTS.common.DISTRICT ) { + district["locationId"] = location.id; + district["name"] = location.name; + } + } + + for (const org of userProfile["organisations"]) { + let orgData = {}; + orgData.orgName = org.orgName; + orgData.organisationId = org.organisationId; + organisation.push(orgData); + } + + let solutionDocument = await solutionsQueries.solutionsDocument({ + _id: solutionId + }, + [ + "_id", + "reportInformation" + ] + ); + + if( !solutionDocument.length > 0 ) { + throw { + message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } + } + + let reportInformation = solutionDocument.reportInformation ? solutionDocument.reportInformation : {}; + if ( reportInformation ) { + reportInformation["districts"] = []; + reportInformation["districts"].push(district); + reportInformation["organisations"] = organisation; + } else { + + const checkDistrictExist = reportInformation["districts"].some(eachDistrict => { + if (eachDistrict.locationId == district["locationId"]) { + return true; + } + }); + + if ( !checkDistrictExist ) { + reportInformation["districts"].push(district); + } + + reportInformation["organisations"].concat(organisation); + } + + await solutionsQueries.updateSolutionDocument + ( + { _id : solutionId }, + { $set : { reportInformation: reportInformation } } + ) + + return resolve({ + success: true, + data: [] + }); + + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: [] + }); + } + }) +} + From 3b228a0ef582a5faccdb173827c7ed4693c1fc01 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 19 Apr 2022 12:22:38 +0530 Subject: [PATCH 127/373] cleanup --- module/userProjects/helper.js | 109 +++++++++++++++++----------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6e806bd7..d4a85fbf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1247,7 +1247,6 @@ module.exports = class UserProjectsHelper { if ( addReportInfoToSolution && project.solutionId ) { await _addReportInformationInSolution( - project._id, project.solutionId, project.userProfile ); @@ -2099,7 +2098,6 @@ module.exports = class UserProjectsHelper { if ( addReportInfoToSolution && projectCreation._doc.solutionId ) { await _addReportInformationInSolution( - projectCreation._doc._id, projectCreation._doc.solutionId, projectCreation._doc.userProfile ); @@ -2931,75 +2929,80 @@ function _projectData(data) { } /** - * Entities information for project. + * Update Report Information In Solutions. * @method * @name _addReportInformationInSolution - * @param {String} entityIds - entity id. - * @returns {Object} Project entity information. + * @param {String} solutionId - solution id. + * @param {Object} userProfile - user read response + * @returns {Object} Solution information. */ -function _addReportInformationInSolution(projectId, solutionId, userProfile = {}) { +function _addReportInformationInSolution(solutionId = "", userProfile = {}) { return new Promise(async (resolve, reject) => { try { - let district = {}; - let organisation = []; + if ( userProfile && solutionId ) { + + let district = {}; + let organisation = []; - for (const location of userProfile["userLocations"]) { - if ( location.type == CONSTANTS.common.DISTRICT ) { - district["locationId"] = location.id; - district["name"] = location.name; + for (const location of userProfile["userLocations"]) { + if ( location.type == CONSTANTS.common.DISTRICT ) { + district["locationId"] = location.id; + district["name"] = location.name; + } } - } - for (const org of userProfile["organisations"]) { - let orgData = {}; - orgData.orgName = org.orgName; - orgData.organisationId = org.organisationId; - organisation.push(orgData); - } + for (const org of userProfile["organisations"]) { + let orgData = {}; + orgData.orgName = org.orgName; + orgData.organisationId = org.organisationId; + organisation.push(orgData); + } - let solutionDocument = await solutionsQueries.solutionsDocument({ - _id: solutionId - }, - [ - "_id", - "reportInformation" - ] - ); - - if( !solutionDocument.length > 0 ) { - throw { - message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status + let solutionDocument = await solutionsQueries.solutionsDocument({ + _id: solutionId + }, + [ + "_id", + "reportInformation" + ] + ); + + if( !solutionDocument.length > 0 ) { + throw { + message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } } - } - let reportInformation = solutionDocument.reportInformation ? solutionDocument.reportInformation : {}; - if ( reportInformation ) { - reportInformation["districts"] = []; - reportInformation["districts"].push(district); - reportInformation["organisations"] = organisation; - } else { + let reportInformation = solutionDocument.reportInformation ? solutionDocument.reportInformation : {}; + if ( reportInformation ) { + reportInformation["districts"] = []; + reportInformation["districts"].push(district); + reportInformation["organisations"] = organisation; + } else { - const checkDistrictExist = reportInformation["districts"].some(eachDistrict => { - if (eachDistrict.locationId == district["locationId"]) { - return true; - } - }); + const checkDistrictExist = reportInformation["districts"].some(eachDistrict => { + if (eachDistrict.locationId == district["locationId"]) { + return true; + } + }); - if ( !checkDistrictExist ) { - reportInformation["districts"].push(district); + if ( !checkDistrictExist ) { + reportInformation["districts"].push(district); + } + + reportInformation["organisations"].concat(organisation); } - reportInformation["organisations"].concat(organisation); + await solutionsQueries.updateSolutionDocument + ( + { _id : solutionId }, + { $set : { reportInformation: reportInformation } } + ) } - - await solutionsQueries.updateSolutionDocument - ( - { _id : solutionId }, - { $set : { reportInformation: reportInformation } } - ) + return resolve({ success: true, From f3abdd55aebb58814ca98b1cdc2235439e88009b Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 19 Apr 2022 13:02:29 +0530 Subject: [PATCH 128/373] fix --- module/userProjects/helper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index d4a85fbf..b79b104d 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2976,6 +2976,7 @@ function _addReportInformationInSolution(solutionId = "", userProfile = {}) { } } + solutionDocument = solutionDocument[0]; let reportInformation = solutionDocument.reportInformation ? solutionDocument.reportInformation : {}; if ( reportInformation ) { reportInformation["districts"] = []; From 332d4336d9585bfa18ed4d91e5eff03c370d98ff Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 20 Apr 2022 10:24:08 +0530 Subject: [PATCH 129/373] add new keys to req for ml-report internal api call --- module/userProjects/helper.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 93bce04f..7549b42e 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1581,7 +1581,11 @@ module.exports = class UserProjectsHelper { "endDate", "tasks", "categories", - "programInformation.name" + "programInformation.name", + "recommendedFor", + "link", + "remarks", + "taskReport.completed" ] ); } @@ -1592,7 +1596,7 @@ module.exports = class UserProjectsHelper { { "$match": { _id: ObjectId(projectId), isDeleted: false} }, { "$project": { "status": 1, "title": 1, "startDate": 1, "metaInformation.goal": 1, "metaInformation.duration":1, - "categories" : 1, "programInformation.name": 1, "description" : 1, + "categories" : 1, "programInformation.name": 1, "description" : 1, "recommendedFor" : 1, "link" : 1, tasks: { "$filter": { input: '$tasks', as: 'tasks', @@ -1609,18 +1613,30 @@ module.exports = class UserProjectsHelper { status: HTTP_STATUS_CODE['bad_request'].status } } - + console.log("projectDocument before : ",projectDocument) projectDocument = projectDocument[0]; projectDocument.goal = projectDocument.metaInformation ? projectDocument.metaInformation.goal : ""; projectDocument.duration = projectDocument.metaInformation ? projectDocument.metaInformation.duration : ""; projectDocument.programName = projectDocument.programInformation ? projectDocument.programInformation.name : ""; + projectDocument.remarks = projectDocument.remarks ? projectDocument.remarks : ""; + projectDocument.taskcompleted = projectDocument.taskReport.completed ? projectDocument.taskReport.completed : 0; + projectDocument.category = []; + if (projectDocument.categories && projectDocument.categories.length > 0) { projectDocument.categories.forEach( category => { projectDocument.category.push(category.name); }) } + + projectDocument.recommendedForRoles = []; + + if (projectDocument.recommendedFor && projectDocument.recommendedFor.length > 0) { + projectDocument.recommendedFor.forEach( recommend => { + projectDocument.recommendedForRoles.push(recommend.code); + }) + } let tasks = []; if (projectDocument.tasks.length > 0) { @@ -1644,12 +1660,12 @@ module.exports = class UserProjectsHelper { delete projectDocument.categories; delete projectDocument.metaInformation; delete projectDocument.programInformation; - + delete projectDocument.recommendedFor; if (UTILS.revertStatusorNot(appVersion)) { projectDocument.status = UTILS.revertProjectStatus(projectDocument.status); } - + console.log("projectDocument : ",projectDocument) let response = await reportService.projectAndTaskReport(userToken, projectDocument, projectPdf); if (response && response.success == true) { From 5af35f6cd76f77e34f3d489d45dce1481e5f47be Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 20 Apr 2022 10:57:03 +0530 Subject: [PATCH 130/373] PR review resolves --- generics/constants/common.js | 3 ++- generics/services/users.js | 5 ++--- module/userProjects/helper.js | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index 237b396e..d5423a15 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -45,5 +45,6 @@ module.exports = { "ATTACHMENT_TYPE_LINK" : "link", "PROJECT_ATTACHMENT" : "project", "TASK_ATTACHMENT" : "task", - "DISTRICT": "district" + "DISTRICT": "district", + "SERVER_TIME_OUT" : 5000 }; diff --git a/generics/services/users.js b/generics/services/users.js index f4c1dc94..ac3790e5 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -8,12 +8,11 @@ //dependencies const request = require('request'); const userServiceUrl = process.env.USER_SERVICE_URL; -const serverTimeout = process.env.SUNBIRD_SERVER_TIMEOUT ? parseInt(process.env.SUNBIRD_SERVER_TIMEOUT) : 5000; const profile = function ( token,userId = "" ) { return new Promise(async (resolve, reject) => { try { - + let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_V5; if( userId !== "" ) { @@ -52,7 +51,7 @@ const profile = function ( token,userId = "" ) { return reject (result = { success : false }); - }, serverTimeout); + }, CONSTANTS.common.SERVER_TIME_OUT); } catch (error) { return reject(error); diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index b79b104d..9ccf884e 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,7 +21,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); -const sunbirdUserProfile = require(GENERICS_FILES_PATH + "/services/users"); +const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); /** @@ -1230,7 +1230,7 @@ module.exports = class UserProjectsHelper { } else { //Fetch user profile information by calling sunbird's user read api. - let userProfile = await sunbirdUserProfile.profile(userToken, userId); + let userProfile = await userProfileService.profile(userToken, userId); if ( userProfile.success && userProfile.data && userProfile.data.response @@ -1417,7 +1417,7 @@ module.exports = class UserProjectsHelper { //Fetch user profile information by calling sunbird's user read api. - let userProfile = await sunbirdUserProfile.profile(userToken, userId); + let userProfile = await userProfileService.profile(userToken, userId); if ( userProfile.success && userProfile.data && userProfile.data.response @@ -2067,7 +2067,7 @@ module.exports = class UserProjectsHelper { } //Fetch user profile information by calling sunbird's user read api. let addReportInfoToSolution = false; - let userProfile = await sunbirdUserProfile.profile(userToken, userId); + let userProfile = await userProfileService.profile(userToken, userId); if ( userProfile.success && userProfile.data && userProfile.data.response From 4a72061aed15d99754ba6884657e745793e792b6 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 20 Apr 2022 13:14:08 +0530 Subject: [PATCH 131/373] PR changes --- module/solutions/helper.js | 79 ++++++++++++++++++++++++++ module/userProjects/helper.js | 103 ++-------------------------------- 2 files changed, 83 insertions(+), 99 deletions(-) diff --git a/module/solutions/helper.js b/module/solutions/helper.js index 87e51da9..153e4fd7 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -8,6 +8,7 @@ // Dependencies const coreService = require(GENERICS_FILES_PATH + "/services/core"); +const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); /** * SolutionsHelper @@ -59,4 +60,82 @@ module.exports = class SolutionsHelper { }); } + /** + * Update User District and Organisation In Solutions For Reporting. + * @method + * @name _addReportInformationInSolution + * @param {String} solutionId - solution id. + * @param {Object} userProfile - user profile details + * @returns {Object} Solution information. +*/ + + static addReportInformationInSolution(solutionId,userProfile) { + return new Promise(async (resolve, reject) => { + try { + + //check solution & userProfile is exist + if ( solutionId && Object.keys(userProfile).length > 0 ) { + console.log("inside") + let district = []; + let organisation = []; + + //get the districts from the userProfile + for (const location of userProfile["userLocations"]) { + if ( location.type == CONSTANTS.common.DISTRICT ) { + let distData = {} + distData["locationId"] = location.id; + distData["name"] = location.name; + district.push(distData); + } + } + + //get the organisations from the userProfile + for (const org of userProfile["organisations"]) { + let orgData = {}; + orgData.orgName = org.orgName; + orgData.organisationId = org.organisationId; + organisation.push(orgData); + } + + //checking solution is exist + let solutionDocument = await solutionsQueries.solutionsDocument({ + _id: solutionId + }, + ["_id"]); + + if( !solutionDocument.length > 0 ) { + throw { + message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } + } + + let updateQuery = {}; + updateQuery["$addToSet"] = {}; + updateQuery["$addToSet"]["reportInformation.organisations"] = { $each : organisation}; + updateQuery["$addToSet"]["reportInformation.districts"] = { $each : district}; + + //add user district and organisation in solution + await solutionsQueries.updateSolutionDocument + ( + { _id : solutionId }, + updateQuery + ) + } + + return resolve({ + success: true, + data: [] + }); + + } catch (error) { + return resolve({ + success : false, + message : error.message, + data: [] + }); + } + }); + } + }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9ccf884e..3f96a64f 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -22,7 +22,7 @@ const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); -const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); +const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); /** * UserProjectsHelper @@ -1244,12 +1244,12 @@ module.exports = class UserProjectsHelper { projectCreation.data.userRoleInformation = userRoleInformation; let project = await projectQueries.createProject(projectCreation.data); - + if ( addReportInfoToSolution && project.solutionId ) { - await _addReportInformationInSolution( + await solutionsHelper.addReportInformationInSolution( project.solutionId, project.userProfile - ); + ); } await kafkaProducersHelper.pushProjectToKafka(project); @@ -2928,100 +2928,5 @@ function _projectData(data) { }) } -/** - * Update Report Information In Solutions. - * @method - * @name _addReportInformationInSolution - * @param {String} solutionId - solution id. - * @param {Object} userProfile - user read response - * @returns {Object} Solution information. -*/ - -function _addReportInformationInSolution(solutionId = "", userProfile = {}) { - return new Promise(async (resolve, reject) => { - try { - - if ( userProfile && solutionId ) { - - let district = {}; - let organisation = []; - - for (const location of userProfile["userLocations"]) { - if ( location.type == CONSTANTS.common.DISTRICT ) { - district["locationId"] = location.id; - district["name"] = location.name; - } - } - - for (const org of userProfile["organisations"]) { - let orgData = {}; - orgData.orgName = org.orgName; - orgData.organisationId = org.organisationId; - organisation.push(orgData); - } - - let solutionDocument = await solutionsQueries.solutionsDocument({ - _id: solutionId - }, - [ - "_id", - "reportInformation" - ] - ); - - if( !solutionDocument.length > 0 ) { - throw { - message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - solutionDocument = solutionDocument[0]; - let reportInformation = solutionDocument.reportInformation ? solutionDocument.reportInformation : {}; - if ( reportInformation ) { - reportInformation["districts"] = []; - reportInformation["districts"].push(district); - reportInformation["organisations"] = organisation; - } else { - - const checkDistrictExist = reportInformation["districts"].some(eachDistrict => { - if (eachDistrict.locationId == district["locationId"]) { - return true; - } - }); - - if ( !checkDistrictExist ) { - reportInformation["districts"].push(district); - } - - reportInformation["organisations"].concat(organisation); - } - - await solutionsQueries.updateSolutionDocument - ( - { _id : solutionId }, - { $set : { reportInformation: reportInformation } } - ) - } - - - return resolve({ - success: true, - data: [] - }); - - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] - }); - } - }) -} - From de45fcb8fa1b5728756ce95c98295862014fa406 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 20 Apr 2022 13:15:01 +0530 Subject: [PATCH 132/373] PR changes --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 3f96a64f..3612c497 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2097,7 +2097,7 @@ module.exports = class UserProjectsHelper { if ( addReportInfoToSolution && projectCreation._doc.solutionId ) { - await _addReportInformationInSolution( + await solutionsHelper.addReportInformationInSolution( projectCreation._doc.solutionId, projectCreation._doc.userProfile ); From f5bb32bbad490ab810c9a494b306257ea69fe713 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 20 Apr 2022 13:20:49 +0530 Subject: [PATCH 133/373] remove console --- module/solutions/helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/module/solutions/helper.js b/module/solutions/helper.js index 153e4fd7..cd0f3652 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -75,7 +75,6 @@ module.exports = class SolutionsHelper { //check solution & userProfile is exist if ( solutionId && Object.keys(userProfile).length > 0 ) { - console.log("inside") let district = []; let organisation = []; From a68896aae61fcb40b98880a3b32227826deb155f Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 20 Apr 2022 13:39:26 +0530 Subject: [PATCH 134/373] PR changes --- generics/constants/api-responses.js | 3 ++- module/solutions/helper.js | 2 ++ module/userProjects/helper.js | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index e7113016..9b85a71f 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -123,5 +123,6 @@ module.exports = { "PROJECT_TEMPLATE_TASK_UPDATED" : "Successfully updated project template task", "TEMPLATE_ID_OR_LINK_REQUIRED" : "TemplateId or Link either one is required", "TEMPLATE_ID_NOT_FOUND_IN_SOLUTION" : "Could not found templateId in solution", - "FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED" : "Failed to sync, Project is already Submitted" + "FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED" : "Failed to sync, Project is already Submitted", + "SOLUTION_ID_AND_USERPROFILE_REQUIRED": "Required solution Id and userProfile" }; diff --git a/module/solutions/helper.js b/module/solutions/helper.js index cd0f3652..b5b468ab 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -120,6 +120,8 @@ module.exports = class SolutionsHelper { { _id : solutionId }, updateQuery ) + } else { + throw new Error(CONSTANTS.apiResponses.SOLUTION_ID_AND_USERPROFILE_REQUIRED); } return resolve({ diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 3612c497..6dfffafd 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1246,7 +1246,7 @@ module.exports = class UserProjectsHelper { let project = await projectQueries.createProject(projectCreation.data); if ( addReportInfoToSolution && project.solutionId ) { - await solutionsHelper.addReportInformationInSolution( + let updateSolution = await solutionsHelper.addReportInformationInSolution( project.solutionId, project.userProfile ); @@ -2097,7 +2097,7 @@ module.exports = class UserProjectsHelper { if ( addReportInfoToSolution && projectCreation._doc.solutionId ) { - await solutionsHelper.addReportInformationInSolution( + let updateSolution = await solutionsHelper.addReportInformationInSolution( projectCreation._doc.solutionId, projectCreation._doc.userProfile ); From 19f633f008878fa1c0831c15cfa3f06bb1b4c286 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 20 Apr 2022 14:55:17 +0530 Subject: [PATCH 135/373] link added --- module/userProjects/helper.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 7549b42e..4fdaa200 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1621,6 +1621,16 @@ module.exports = class UserProjectsHelper { projectDocument.remarks = projectDocument.remarks ? projectDocument.remarks : ""; projectDocument.taskcompleted = projectDocument.taskReport.completed ? projectDocument.taskReport.completed : 0; + //adding for test purpose + projectDocument.evidenceLink = ["https://www.youtube.com/watch?v=C2Z5-IfvdcQ&list=RDCMUCj_iGliGCkLcHSZ8eqVNPDQ&start_radio=1&rv=C2Z5-IfvdcQ&t=13", + "https://www.youtube.com/watch?v=N6fspIf42U8" + ]; + + projectDocument.imageLink = [ + "https://irisholidays.com/keralatourism/wp-content/uploads/2021/10/Kerala-peaks-1-1536x864.jpg", + "https://irisholidays.com/keralatourism/wp-content/uploads/2021/10/Kerala-peaks-1-1536x864.jpg", + "https://irisholidays.com/keralatourism/wp-content/uploads/2021/10/Kerala-peaks-1-1536x864.jpg" + ]; projectDocument.category = []; From d57a178cd6dcc74259adf7d41b99e471d26ad815 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 20 Apr 2022 14:57:06 +0530 Subject: [PATCH 136/373] timeout change --- generics/services/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/services/users.js b/generics/services/users.js index ac3790e5..17ceb69a 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -48,7 +48,7 @@ const profile = function ( token,userId = "" ) { return resolve(result); } setTimeout(function () { - return reject (result = { + return resolve (result = { success : false }); }, CONSTANTS.common.SERVER_TIME_OUT); From ec62686f9b9f5b63c4cab4c474eeb2c46af88f47 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 21 Apr 2022 17:34:13 +0530 Subject: [PATCH 137/373] Pr changes --- module/solutions/helper.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/module/solutions/helper.js b/module/solutions/helper.js index b5b468ab..0d3f7a54 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -74,7 +74,11 @@ module.exports = class SolutionsHelper { try { //check solution & userProfile is exist - if ( solutionId && Object.keys(userProfile).length > 0 ) { + if ( + solutionId && userProfile && + userProfile["userLocations"] && + userProfile["organisations"] + ) { let district = []; let organisation = []; @@ -111,8 +115,14 @@ module.exports = class SolutionsHelper { let updateQuery = {}; updateQuery["$addToSet"] = {}; - updateQuery["$addToSet"]["reportInformation.organisations"] = { $each : organisation}; - updateQuery["$addToSet"]["reportInformation.districts"] = { $each : district}; + + if ( organisation.length > 0 ) { + updateQuery["$addToSet"]["reportInformation.organisations"] = { $each : organisation}; + } + + if ( district.length > 0 ) { + updateQuery["$addToSet"]["reportInformation.districts"] = { $each : district}; + } //add user district and organisation in solution await solutionsQueries.updateSolutionDocument @@ -126,7 +136,7 @@ module.exports = class SolutionsHelper { return resolve({ success: true, - data: [] + message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY }); } catch (error) { From 4c28823e9d460f3b26ef38df8fb3060f0a49828c Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 22 Apr 2022 09:59:52 +0530 Subject: [PATCH 138/373] fixes --- module/solutions/helper.js | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/module/solutions/helper.js b/module/solutions/helper.js index 0d3f7a54..87b0b507 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -100,22 +100,9 @@ module.exports = class SolutionsHelper { organisation.push(orgData); } - //checking solution is exist - let solutionDocument = await solutionsQueries.solutionsDocument({ - _id: solutionId - }, - ["_id"]); - - if( !solutionDocument.length > 0 ) { - throw { - message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - let updateQuery = {}; updateQuery["$addToSet"] = {}; - + if ( organisation.length > 0 ) { updateQuery["$addToSet"]["reportInformation.organisations"] = { $each : organisation}; } @@ -125,11 +112,14 @@ module.exports = class SolutionsHelper { } //add user district and organisation in solution - await solutionsQueries.updateSolutionDocument - ( - { _id : solutionId }, - updateQuery - ) + if ( updateQuery["$addToSet"] && Object.keys(updateQuery["$addToSet"].length > 0)) { + await solutionsQueries.updateSolutionDocument + ( + { _id : solutionId }, + updateQuery + ) + } + } else { throw new Error(CONSTANTS.apiResponses.SOLUTION_ID_AND_USERPROFILE_REQUIRED); } From 917f1773aa7922a8910cd82853d6b1798924e475 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Fri, 22 Apr 2022 12:39:23 +0530 Subject: [PATCH 139/373] stoey SB-29621 --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6dfffafd..f2ad424c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1788,7 +1788,8 @@ module.exports = class UserProjectsHelper { "solutionExternalId", "lastDownloadedAt", "hasAcceptedTAndC", - "referenceFrom" + "referenceFrom", + "status" ] ); From 494a6dbf75142c4772fcbdccac757ed0635d17bb Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 22 Apr 2022 14:41:33 +0530 Subject: [PATCH 140/373] url generation change and new key added --- controllers/v1/userProjects.js | 1 - generics/constants/common.js | 4 ++- module/userProjects/helper.js | 62 ++++++++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 2c390f9c..e8019d26 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -647,7 +647,6 @@ module.exports = class UserProjects extends Abstract { req.userDetails.userToken, req.headers['x-app-ver'] ); - return resolve({ message: report.message, result: report.data diff --git a/generics/constants/common.js b/generics/constants/common.js index 009bf7e9..34212fce 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -44,5 +44,7 @@ module.exports = { "CHILDREN" : "children", "ATTACHMENT_TYPE_LINK" : "link", "PROJECT_ATTACHMENT" : "project", - "TASK_ATTACHMENT" : "task" + "TASK_ATTACHMENT" : "task", + "DEFAULT_TASK_COMPLETED" : 0, + "IMAGE_DATA_TYPE" : "image/jpeg" }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4fdaa200..5343ae1b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1585,6 +1585,7 @@ module.exports = class UserProjectsHelper { "recommendedFor", "link", "remarks", + "attachments", "taskReport.completed" ] ); @@ -1596,7 +1597,7 @@ module.exports = class UserProjectsHelper { { "$match": { _id: ObjectId(projectId), isDeleted: false} }, { "$project": { "status": 1, "title": 1, "startDate": 1, "metaInformation.goal": 1, "metaInformation.duration":1, - "categories" : 1, "programInformation.name": 1, "description" : 1, "recommendedFor" : 1, "link" : 1, + "categories" : 1, "programInformation.name": 1, "description" : 1, "recommendedFor" : 1, "link" : 1, "remarks" : 1, "attachments" : 1, "taskReport.completed" : 1, tasks: { "$filter": { input: '$tasks', as: 'tasks', @@ -1613,26 +1614,55 @@ module.exports = class UserProjectsHelper { status: HTTP_STATUS_CODE['bad_request'].status } } - console.log("projectDocument before : ",projectDocument) + projectDocument = projectDocument[0]; projectDocument.goal = projectDocument.metaInformation ? projectDocument.metaInformation.goal : ""; projectDocument.duration = projectDocument.metaInformation ? projectDocument.metaInformation.duration : ""; projectDocument.programName = projectDocument.programInformation ? projectDocument.programInformation.name : ""; projectDocument.remarks = projectDocument.remarks ? projectDocument.remarks : ""; - projectDocument.taskcompleted = projectDocument.taskReport.completed ? projectDocument.taskReport.completed : 0; + projectDocument.taskcompleted = projectDocument.taskReport.completed ? projectDocument.taskReport.completed : CONSTANTS.common.DEFAULT_TASK_COMPLETED; + + //store tasks and attachment data into object + let projectFilter = { + tasks : projectDocument.tasks, + attachments : projectDocument.attachments + } + + //returns project tasks and attachments with downloadable urls + let projectDataWithUrl = await _projectInformation( projectFilter ); + + //replace projectDocument Data + if ( projectDataWithUrl && + projectDataWithUrl.tasks && + projectDataWithUrl.tasks.length > 0 + ) { + projectDocument.tasks = projectDataWithUrl.tasks ; + } + if ( projectDataWithUrl && + projectDataWithUrl.attachments && + projectDataWithUrl.attachments.length > 0 + ) { + projectDocument.attachments = projectDataWithUrl.attachments ; + } + + //get image link and other document links + let imageLink = []; + let evidenceLink = []; + if ( projectDocument.attachments && projectDocument.attachments.length > 0 ) { + projectDocument.attachments.forEach( attachment => { + if( attachment.type == CONSTANTS.common.IMAGE_DATA_TYPE && attachment.url && attachment.url !== "" ) { + imageLink.push( attachment.url ); + } else if ( attachment.url && attachment.url !== "" ) { + evidenceLink.push( attachment.url ); + } + }) + } //adding for test purpose - projectDocument.evidenceLink = ["https://www.youtube.com/watch?v=C2Z5-IfvdcQ&list=RDCMUCj_iGliGCkLcHSZ8eqVNPDQ&start_radio=1&rv=C2Z5-IfvdcQ&t=13", - "https://www.youtube.com/watch?v=N6fspIf42U8" - ]; - - projectDocument.imageLink = [ - "https://irisholidays.com/keralatourism/wp-content/uploads/2021/10/Kerala-peaks-1-1536x864.jpg", - "https://irisholidays.com/keralatourism/wp-content/uploads/2021/10/Kerala-peaks-1-1536x864.jpg", - "https://irisholidays.com/keralatourism/wp-content/uploads/2021/10/Kerala-peaks-1-1536x864.jpg" - ]; - projectDocument.category = []; - + projectDocument.evidenceLink = evidenceLink; + projectDocument.imageLink = imageLink; + + projectDocument.category = []; if (projectDocument.categories && projectDocument.categories.length > 0) { projectDocument.categories.forEach( category => { @@ -1675,7 +1705,7 @@ module.exports = class UserProjectsHelper { if (UTILS.revertStatusorNot(appVersion)) { projectDocument.status = UTILS.revertProjectStatus(projectDocument.status); } - console.log("projectDocument : ",projectDocument) + let response = await reportService.projectAndTaskReport(userToken, projectDocument, projectPdf); if (response && response.success == true) { @@ -2892,3 +2922,5 @@ function _projectData(data) { + + From 887febc94948bec04413329f7db413917a004155 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 25 Apr 2022 09:23:32 +0530 Subject: [PATCH 141/373] comment removed --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 5343ae1b..a72938fa 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1658,7 +1658,7 @@ module.exports = class UserProjectsHelper { } }) } - //adding for test purpose + projectDocument.evidenceLink = evidenceLink; projectDocument.imageLink = imageLink; From 5957948c6a6d63c474ebe82396207b19d1e1772d Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 26 Apr 2022 16:25:13 +0530 Subject: [PATCH 142/373] comma added --- generics/constants/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index 4a691253..d8440a78 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -46,7 +46,7 @@ module.exports = { "PROJECT_ATTACHMENT" : "project", "TASK_ATTACHMENT" : "task", "DEFAULT_TASK_COMPLETED" : 0, - "IMAGE_DATA_TYPE" : "image/jpeg" + "IMAGE_DATA_TYPE" : "image/jpeg", "DISTRICT": "district", "SERVER_TIME_OUT" : 5000 }; From b0cbe769561b30953b9e6a034edef6df6c4475a7 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 29 Apr 2022 17:38:02 +0530 Subject: [PATCH 143/373] issue resolves --- module/userProjects/helper.js | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index a0582770..10124108 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1672,24 +1672,28 @@ module.exports = class UserProjectsHelper { tasks : projectDocument.tasks, attachments : projectDocument.attachments } - + //returns project tasks and attachments with downloadable urls let projectDataWithUrl = await _projectInformation( projectFilter ); //replace projectDocument Data - if ( projectDataWithUrl && - projectDataWithUrl.tasks && - projectDataWithUrl.tasks.length > 0 + if ( projectDataWithUrl.success && + projectDataWithUrl.data && + projectDataWithUrl.data.tasks && + projectDataWithUrl.data.tasks.length > 0 ) { - projectDocument.tasks = projectDataWithUrl.tasks ; + + projectDocument.tasks = projectDataWithUrl.data.tasks ; } - if ( projectDataWithUrl && - projectDataWithUrl.attachments && - projectDataWithUrl.attachments.length > 0 + if ( projectDataWithUrl.success && + projectDataWithUrl.data && + projectDataWithUrl.data.attachments && + projectDataWithUrl.data.attachments.length > 0 ) { - projectDocument.attachments = projectDataWithUrl.attachments ; + projectDocument.attachments = projectDataWithUrl.data.attachments ; } + //get image link and other document links let imageLink = []; @@ -1698,12 +1702,21 @@ module.exports = class UserProjectsHelper { projectDocument.attachments.forEach( attachment => { if( attachment.type == CONSTANTS.common.IMAGE_DATA_TYPE && attachment.url && attachment.url !== "" ) { imageLink.push( attachment.url ); + } else if ( attachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK && attachment.name && attachment.name !== "" ) { + let data = { + type : attachment.type, + url : attachment.name + } + evidenceLink.push( data ); } else if ( attachment.url && attachment.url !== "" ) { - evidenceLink.push( attachment.url ); + let data = { + type : attachment.type, + url : attachment.url + } + evidenceLink.push( data ); } }) } - projectDocument.evidenceLink = evidenceLink; projectDocument.imageLink = imageLink; @@ -1750,7 +1763,6 @@ module.exports = class UserProjectsHelper { if (UTILS.revertStatusorNot(appVersion)) { projectDocument.status = UTILS.revertProjectStatus(projectDocument.status); } - let response = await reportService.projectAndTaskReport(userToken, projectDocument, projectPdf); if (response && response.success == true) { @@ -2272,7 +2284,7 @@ function _projectInformation(project) { projectAttachments.push(currentProjectAttachment.sourcePath); } } - + let projectAttachmentsUrl = await _attachmentInformation(projectAttachments, projectLinkAttachments, project.attachments, CONSTANTS.common.PROJECT_ATTACHMENT); if ( projectAttachmentsUrl.data && projectAttachmentsUrl.data.length > 0 ) { project.attachments = projectAttachmentsUrl.data; @@ -2434,6 +2446,7 @@ function _attachmentInformation ( attachmentWithSourcePath = [], linkAttachments if (type === CONSTANTS.common.PROJECT_ATTACHMENT ) { attachments.concat(linkAttachments); + } else { From aa6d42c8b20183bb89c783de8370774b2d99c0d9 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 11 May 2022 15:54:30 +0530 Subject: [PATCH 144/373] status check --- module/userProjects/helper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 10124108..c98ca465 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -339,7 +339,9 @@ module.exports = class UserProjectsHelper { } } - updateProject.status = UTILS.convertProjectStatus(data.status); + if ( data.status && data.status !== "" ) { + updateProject.status = UTILS.convertProjectStatus(data.status); + } if ( data.status == CONSTANTS.common.COMPLETED_STATUS || data.status == CONSTANTS.common.SUBMITTED_STATUS ) { updateProject.completedDate = new Date(); From c9128bd0c08a0c6585163e7b01554d1e1029b0b6 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Thu, 26 May 2022 11:10:35 +0530 Subject: [PATCH 145/373] remove schools from organisation in solution --- module/solutions/helper.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/module/solutions/helper.js b/module/solutions/helper.js index 87b0b507..5a0c54c7 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -94,10 +94,13 @@ module.exports = class SolutionsHelper { //get the organisations from the userProfile for (const org of userProfile["organisations"]) { - let orgData = {}; - orgData.orgName = org.orgName; - orgData.organisationId = org.organisationId; - organisation.push(orgData); + if ( !org.isSchool ) { + let orgData = {}; + orgData.orgName = org.orgName; + orgData.organisationId = org.organisationId; + organisation.push(orgData); + } + } let updateQuery = {}; From 4d12ac75c1d43c007f9c99d70f8f1f0e63878b4e Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 1 Jun 2022 09:09:47 +0530 Subject: [PATCH 146/373] overdue bug fix --- module/reports/helper.js | 105 ++++++++++++++++++++-------------- module/userProjects/helper.js | 49 ++++++++++++---- 2 files changed, 99 insertions(+), 55 deletions(-) diff --git a/module/reports/helper.js b/module/reports/helper.js index e49a5793..aec84087 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -37,7 +37,6 @@ module.exports = class ReportsHelper { static entity(entityId = "", userId, userToken, userName, reportType, programId = "", getPdf,appVersion) { return new Promise(async (resolve, reject) => { try { - let query = { }; if (entityId) { query["entityId"] = ObjectId(entityId); @@ -64,10 +63,10 @@ module.exports = class ReportsHelper { { "syncedAt": { $gte: new Date(startFrom), $lte: new Date(endOf) } }, { "tasks": { $elemMatch: { isDeleted: { $ne: true },syncedAt: { $gte: new Date(startFrom), $lte: new Date(endOf) } } } }, ] - + const projectDetails = await projectQueries.projectDocument( query, - ["programId","programInformation.name", "entityInformation.name", "taskReport", "status", "tasks", "categories"], + ["programId","programInformation.name", "entityInformation.name", "taskReport", "status", "tasks", "categories", "endDate"], [] ); @@ -101,9 +100,7 @@ module.exports = class ReportsHelper { }); - - - if (!projectDetails.length > 0) { + if ( !projectDetails.length > 0 ) { if (getPdf == true) { @@ -167,8 +164,8 @@ module.exports = class ReportsHelper { } await Promise.all(projectDetails.map(async function (project) { - - if (project.categories) { + + if ( project.categories ) { project.categories.map(category => { if( @@ -189,61 +186,64 @@ module.exports = class ReportsHelper { categories['total'] = categories['total'] + project.categories.length; } - let todayDate = moment(project.endDate, "DD.MM.YYYY"); - let endDate = moment().format(); - - if (project.status == CONSTANTS.common.SUBMITTED_STATUS) { + //Add data into projectReport and check project overdue. + if ( project.status == CONSTANTS.common.SUBMITTED_STATUS ) { projectReport[CONSTANTS.common.SUBMITTED_STATUS] = projectReport[CONSTANTS.common.SUBMITTED_STATUS] + 1; - } else if (project.status == CONSTANTS.common.INPROGRESS_STATUS) { - - if (todayDate.diff(endDate, 'days') < 1) { + } else if ( project.status == CONSTANTS.common.INPROGRESS_STATUS || project.status == CONSTANTS.common.STARTED ) { + //Returns project overdue status true/false. + let overdue = _getOverdueStatus( project.endDate ); + + if ( overdue ) { projectReport['overdue'] = projectReport['overdue'] + 1; } else { - projectReport[CONSTANTS.common.INPROGRESS_STATUS] = projectReport[CONSTANTS.common.INPROGRESS_STATUS] + 1; - } - - } else if (project.status == CONSTANTS.common.STARTED) { - - if (todayDate.diff(endDate, 'days') < 1) { - projectReport['overdue'] = projectReport['overdue'] + 1; - } else { - projectReport[CONSTANTS.common.STARTED] = projectReport[CONSTANTS.common.STARTED] + 1; + projectReport[project.status] = projectReport[project.status] + 1; } } + //get total project count projectReport["total"] = projectReport[CONSTANTS.common.STARTED] + projectReport['overdue'] + projectReport[CONSTANTS.common.INPROGRESS_STATUS] + projectReport[CONSTANTS.common.SUBMITTED_STATUS]; - if (project.taskReport) { - let keys = Object.keys(project.taskReport); - keys.map(key => { - if (tasksReport[key]) { + //Get tasks summary deatail of project. + if ( project.taskReport ) { + let keys = Object.keys( project.taskReport ); + keys.map( key => { + if ( tasksReport[key] ) { tasksReport[key] = tasksReport[key] + project.taskReport[key]; } else { - tasksReport[key] = project.taskReport[key]; + tasksReport[key] = project.taskReport[key]; } }); } + //Get number of tasks overdued. await Promise.all(project.tasks.map(task => { - let taskCurrentDate = moment(task.endDate, "DD.MM.YYYY"); - if (taskCurrentDate.diff(endDate, 'days') < 1) { - if (tasksReport['overdue']) { - tasksReport['overdue'] = tasksReport['overdue'] + 1; - } else { - tasksReport['overdue'] = 1; - } - if(tasksReport[task.status]){ - tasksReport[task.status] = tasksReport[task.status] - 1; - } + //consider task only if not deleted + if ( task.isDeleted == false && task.status != CONSTANTS.common.COMPLETED_STATUS ){ + + //Returns true or false + let overdue = _getOverdueStatus( task.endDate ); + + if ( overdue ) { + + if ( tasksReport['overdue'] ) { + tasksReport['overdue'] = tasksReport['overdue'] + 1; + } else { + tasksReport['overdue'] = 1; + } + if ( tasksReport[task.status] ) { + tasksReport[task.status] = tasksReport[task.status] - 1; + } + + } } + })); - })); - if (UTILS.revertStatusorNot(appVersion)) { + if ( UTILS.revertStatusorNot(appVersion) ) { projectReport[CONSTANTS.common.COMPLETED_STATUS] = projectReport[CONSTANTS.common.SUBMITTED_STATUS]; projectReport[CONSTANTS.common.NOT_STARTED_STATUS] = projectReport[CONSTANTS.common.STARTED]; @@ -251,7 +251,7 @@ module.exports = class ReportsHelper { delete projectReport[CONSTANTS.common.STARTED]; } - if (getPdf == true) { + if ( getPdf == true ) { let reportTaskData = {}; Object.keys(tasksReport).map(taskData => { @@ -285,7 +285,7 @@ module.exports = class ReportsHelper { pdfRequest['entityName'] = projectDetails[0].entityInformation.name; } - + //send data to report service to generate PDF. let response = await reportService.entityReport(userToken, pdfRequest); if (response && response.success == true) { return resolve({ @@ -683,5 +683,24 @@ function _getDateRangeofReport(reportType) { } +/** + * Get overdue status + * @method + * @name _getOverdueStatus + * @param {String} endDate - date that task or project suppose to be finished. + * @returns {Boolean} - returns overdue status + */ + +function _getOverdueStatus( endDate ) { + let overdue = false; + let today = moment().format(); + let endDateObject = moment( endDate, 'YYYY-MM-DD' ); + + //Find difference between present date and end date + if ( endDateObject.diff( today, 'days' ) < 1 ) { + overdue = true; + } + return overdue; +} diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c98ca465..c6596751 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -295,11 +295,17 @@ module.exports = class UserProjectsHelper { taskReport.total = updateProject.tasks.length; updateProject.tasks.forEach(task => { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; + //consider tasks where isDeleted is false. + if ( task.isDeleted == false ) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } } else { - taskReport[task.status] += 1; + taskReport.total = taskReport.total - 1; } + }); updateProject["taskReport"] = taskReport; @@ -1363,11 +1369,18 @@ module.exports = class UserProjectsHelper { }; result.tasks.forEach(task => { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; + if ( task.isDeleted == false ) { + + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + } else { - taskReport[task.status] += 1; + taskReport.total = taskReport.total - 1; } + }); result["taskReport"] = taskReport; @@ -1504,11 +1517,17 @@ module.exports = class UserProjectsHelper { taskReport.total = createProject.tasks.length; createProject.tasks.forEach(task => { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; + if ( task.isDeleted == false ) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } } else { - taskReport[task.status] += 1; + //if task is deleted it is not counted in total. + taskReport.total = taskReport.total - 1; } + }); createProject["taskReport"] = taskReport; @@ -2056,11 +2075,17 @@ module.exports = class UserProjectsHelper { taskReport.total = libraryProjects.data.tasks.length; libraryProjects.data.tasks.forEach(task => { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; + if ( task.isDeleted == false ) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } } else { - taskReport[task.status] += 1; + //reduce total count if task is deleted. + taskReport.total = taskReport.total - 1; } + }); libraryProjects.data["taskReport"] = taskReport; From d3cf1004d4b24a7fe10ea85d01b28ce41c218218 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 8 Jun 2022 17:21:47 +0530 Subject: [PATCH 147/373] run compound index through model --- config/db/mongodb.js | 13 ++++++++++++- generics/abstract.js | 4 ++++ models/projects.js | 12 +++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/config/db/mongodb.js b/config/db/mongodb.js index 1ba8f648..65be472a 100644 --- a/config/db/mongodb.js +++ b/config/db/mongodb.js @@ -68,11 +68,22 @@ const DB = function() { return model; }; + const runCompoundIndex = function(modelName,opts) { + if (opts && opts.length > 0) { + for ( let indexPointer = 0 ; indexPointer < opts.length ; indexPointer++ ) { + let currentIndex = opts[indexPointer]; + db.collection(modelName).createIndex(currentIndex.name, currentIndex.indexType); + } + } + } + + return { database: db, createModel: createModel, ObjectId: ObjectId, - models: db.models + models: db.models, + runCompoundIndex: runCompoundIndex }; }; diff --git a/generics/abstract.js b/generics/abstract.js index 5a53eb5d..bcad2ea6 100644 --- a/generics/abstract.js +++ b/generics/abstract.js @@ -14,6 +14,10 @@ let Abstract = class Abstract { constructor(schema) { database.createModel(schemas[schema]); + if ( schemas[schema].runIndex && schemas[schema].runIndex.length > 0 ) { + database.runCompoundIndex(schemas[schema].name,schemas[schema].runIndex); + } + } }; diff --git a/models/projects.js b/models/projects.js index 72e67ea2..3c8d3a1a 100644 --- a/models/projects.js +++ b/models/projects.js @@ -136,5 +136,15 @@ module.exports = { }, remarks : String, userProfile : Object - } + }, + runIndex: [ + { + "name" :{ userId: 1, solutionId: 1 }, + "indexType" : { unique: true, partialFilterExpression: { solutionId: { $exists: true }}} + } + ] + + + }; + From 1b13ac00ba459ac07def0a0ae9c4c3d73615ab6d Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 13 Jun 2022 13:46:47 +0530 Subject: [PATCH 148/373] rename to compoundIndex --- config/db/mongodb.js | 3 +-- generics/abstract.js | 4 ++-- models/projects.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/config/db/mongodb.js b/config/db/mongodb.js index 65be472a..5a5d2392 100644 --- a/config/db/mongodb.js +++ b/config/db/mongodb.js @@ -75,8 +75,7 @@ const DB = function() { db.collection(modelName).createIndex(currentIndex.name, currentIndex.indexType); } } - } - + }; return { database: db, diff --git a/generics/abstract.js b/generics/abstract.js index bcad2ea6..7c1d9453 100644 --- a/generics/abstract.js +++ b/generics/abstract.js @@ -14,8 +14,8 @@ let Abstract = class Abstract { constructor(schema) { database.createModel(schemas[schema]); - if ( schemas[schema].runIndex && schemas[schema].runIndex.length > 0 ) { - database.runCompoundIndex(schemas[schema].name,schemas[schema].runIndex); + if ( schemas[schema].compoundIndex && schemas[schema].compoundIndex.length > 0 ) { + database.runCompoundIndex(schemas[schema].name,schemas[schema].compoundIndex); } } diff --git a/models/projects.js b/models/projects.js index 3c8d3a1a..35a91116 100644 --- a/models/projects.js +++ b/models/projects.js @@ -137,7 +137,7 @@ module.exports = { remarks : String, userProfile : Object }, - runIndex: [ + compoundIndex: [ { "name" :{ userId: 1, solutionId: 1 }, "indexType" : { unique: true, partialFilterExpression: { solutionId: { $exists: true }}} From 54c5feda42f449a9849b64bcc66abf167e9295b6 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 20 Jun 2022 18:28:40 +0530 Subject: [PATCH 149/373] added userProfile if the project is not a improvement suggestion --- module/userProjects/helper.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c6596751..245ff30a 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1247,6 +1247,18 @@ module.exports = class UserProjectsHelper { addReportInfoToSolution = true; } } + + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfileData = await userProfileService.profile(userToken, userId); + if ( userProfileData.success && + userProfileData.data && + userProfileData.data.response + ) { + projectCreation.data.userProfile = userProfileData.data.response; + addReportInfoToSolution = true; + } } projectCreation.data.userRoleInformation = userRoleInformation; From c6b7dc98737e69117baa909c4fa5147a93719cc6 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 29 Jun 2022 11:07:15 +0530 Subject: [PATCH 150/373] project status fix --- generics/helpers/utils.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 295cb104..6f83a28c 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -224,12 +224,17 @@ function convertProjectStatus(status) { function revertStatusorNot( appVersion ) { - let appVersionNo = Number(appVersion.split('.',2).join('.')); - - if ( !isNaN(appVersionNo) && appVersionNo < 4.7 ) { - return true - } else { + let appVer = appVersion.split('.',2).join('.'); + if ( appVer == "4.10") { return false + } else { + + let appVersionNo = Number(appVer); + if ( !isNaN(appVersionNo) && appVersionNo < 4.7 ) { + return true + } else { + return false + } } } From a84f655c50ae43fbc84b12e7d5847c4d3cb3d923 Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Wed, 29 Jun 2022 13:59:11 +0530 Subject: [PATCH 151/373] project status fix --- generics/helpers/utils.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 6f83a28c..1f1621b3 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -224,8 +224,10 @@ function convertProjectStatus(status) { function revertStatusorNot( appVersion ) { + let versions = ["4.10", "4.11", "4.12" ]; + let appVer = appVersion.split('.',2).join('.'); - if ( appVer == "4.10") { + if ( versions.includes(appVer)) { return false } else { From 70cb2f330e46cd70a611e59afef5a2ffae914a28 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 22 Jul 2022 13:17:36 +0530 Subject: [PATCH 152/373] resolves_users.js added --- .env.sample | 5 ++++- envVariables.js | 4 ++-- generics/constants/endpoints.js | 2 +- generics/services/{sunbird.js => users.js} | 20 ++++++++------------ module/userProjects/helper.js | 6 +++--- 5 files changed, 18 insertions(+), 19 deletions(-) rename generics/services/{sunbird.js => users.js} (79%) diff --git a/.env.sample b/.env.sample index 81fa286c..f6307ace 100644 --- a/.env.sample +++ b/.env.sample @@ -27,4 +27,7 @@ KAFKA_GROUP_ID = "projects" # SUBMISSION TOPIC SUBMISSION_TOPIC = "dev.sl.projects.submissions" // Kafka topic name for pushing projects submissions -PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.submissions" // project submission topic \ No newline at end of file +PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.submissions" // project submission topic + +# SUNBIRD LOCATION AND USER READ +USER_SERVICE_URL = "http://user-service:3000" // service used for user profile read location search are using this base url \ No newline at end of file diff --git a/envVariables.js b/envVariables.js index f3f893f5..9ccd9f9f 100644 --- a/envVariables.js +++ b/envVariables.js @@ -36,8 +36,8 @@ let enviromentVariables = { "message" : "Required", "optional" : false }, - "SUNBIRD_SERVICE_URL" : { - "message" : "Required sunbird service url", + "USER_SERVICE_URL" : { + "message" : "Required user service base url", "optional" : false } } diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 11e6ea9c..a627540b 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -45,5 +45,5 @@ module.exports = { CREATE_IMPROVEMENT_PROJECT_SOLUTION : "/v1/solutions/create", PROJECT_AND_TASK_REPORT : "/v1/improvement-project/projectAndTaskReport", FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl", - GET_LOCATION_DATA : "/api/data/v1/location/search" + GET_LOCATION_DATA : "/v1/location/search" }; diff --git a/generics/services/sunbird.js b/generics/services/users.js similarity index 79% rename from generics/services/sunbird.js rename to generics/services/users.js index 4ca73220..c407420a 100644 --- a/generics/services/sunbird.js +++ b/generics/services/users.js @@ -1,15 +1,13 @@ /** - * name : sunbird.js - * author : Vishnudas - * Date : 16-March-2022 - * Description : All Sunbird learner related api call. + * name : users.js + * author : Vishnu + * Date : 07-April-2022 + * Description : All users related api call. */ //dependencies - - const request = require('request'); -const sunbirdBaseUrl = process.env.SUNBIRD_SERVICE_URL; +const userServiceUrl = process.env.USER_SERVICE_URL; const serverTimeout = process.env.SUNBIRD_SERVER_TIMEOUT ? parseInt( process.env.SUNBIRD_SERVER_TIMEOUT ) : 5000; /** * @@ -28,10 +26,9 @@ const learnerLocationSearch = function ( filterData ) { bodyData["request"] = {}; bodyData["request"]["filters"] = filterData; const url = - sunbirdBaseUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; + userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; const options = { headers : { - "Authorization" : process.env.SUNBIRD_SERVICE_AUTHERIZATION, "content-type": "application/json" }, json : bodyData @@ -62,7 +59,7 @@ const learnerLocationSearch = function ( filterData ) { } setTimeout(function () { - return reject (result = { + return resolve (result = { success : false }); }, serverTimeout); @@ -72,7 +69,6 @@ const learnerLocationSearch = function ( filterData ) { } }) } - module.exports = { - learnerLocationSearch : learnerLocationSearch + learnerLocationSearch : learnerLocationSearch }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 2a3170b7..865ded02 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,7 +21,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); -const sunbirdService = require(GENERICS_FILES_PATH + '/services/sunbird'); +const sunbirdUserProfile = require(GENERICS_FILES_PATH + "/services/users"); /** * UserProjectsHelper @@ -2482,9 +2482,9 @@ function _entitiesInformation(entityIds) { }; - let entityDetails = await sunbirdService.learnerLocationSearch(bodyData); + let entityDetails = await sunbirdUserProfile.learnerLocationSearch(bodyData); - if (!entityDetails.success || !entityDetails.data || !entityDetails.data.response.length > 0) { + if (!entityDetails.success || !entityDetails.data || !entityDetails.data.response || !entityDetails.data.response.length > 0) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND From 420b0aff856bba01e4fc58dc7cccdcff49879ddf Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 22 Jul 2022 13:22:01 +0530 Subject: [PATCH 153/373] resolve --- module/userProjects/helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 865ded02..949ff975 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1394,7 +1394,7 @@ module.exports = class UserProjectsHelper { } createProject = _.merge(createProject, programAndSolutionInformation.data); - } else{ + } else { let queryData = {}; queryData["_id"] = data.programId; let programDetails = await programsQueries.programsDocument(queryData, @@ -2510,7 +2510,7 @@ function _entitiesInformation(entityIds) { let entitiesData = []; - if ( entities.length > 0 ) { + if ( entityResult.length > 0 ) { entitiesData = _entitiesMetaInformation(entityResult); } From dc13f13e887fd5457ff87c18211b7e1fd02eb24e Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 4 Aug 2022 11:55:25 +0530 Subject: [PATCH 154/373] logic to check for locationCode added --- generics/helpers/utils.js | 33 ++++++++++++++++++++++--- module/userProjects/helper.js | 46 ++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 295cb104..cf7086ff 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -3,9 +3,10 @@ * author : Aman Karki * Date : 13-July-2020 * Description : All utility functions. - */ - - /** +*/ +// Dependencies +const {validate : uuidValidate,v4 : uuidV4} = require('uuid'); +/** * convert camel case to title case. * @function * @name camelCaseToTitleCase @@ -233,6 +234,29 @@ function revertStatusorNot( appVersion ) { } } + +/** + * check whether string is valid uuid. + * @function + * @name checkValidUUID + * @param {String} uuids + * @returns {Boolean} returns a Boolean value true/false +*/ + +function checkValidUUID(uuids) { + + var validateUUID = true; + if(Array.isArray(uuids)){ + for (var i = 0; uuids.length > i; i++) { + if(!uuidValidate(uuids[i])){ + validateUUID = false + } + } + }else { + validateUUID = uuidValidate(uuids); + } + return validateUUID; +} module.exports = { camelCaseToTitleCase : camelCaseToTitleCase, lowerCase : lowerCase, @@ -245,5 +269,6 @@ module.exports = { isValidMongoId : isValidMongoId, convertProjectStatus : convertProjectStatus, revertProjectStatus:revertProjectStatus, - revertStatusorNot:revertStatusorNot + revertStatusorNot:revertStatusorNot, + checkValidUUID : checkValidUUID }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 949ff975..842572ff 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2477,24 +2477,47 @@ function _projectCategories(categories) { function _entitiesInformation(entityIds) { return new Promise(async (resolve, reject) => { try { - let bodyData={ - "id" : entityIds - }; - - - let entityDetails = await sunbirdUserProfile.learnerLocationSearch(bodyData); + let locationIds = []; + let locationCodes = []; + let entityInformations = []; + entityIds.forEach(entity=>{ + if (UTILS.checkValidUUID(entity)) { + locationIds.push(entity); + } else { + locationCodes.push(entity); + } + }); + + if ( locationIds.length > 0 ) { + let bodyData = { + "id" : locationIds + } + let entityData = await sunbirdUserProfile.learnerLocationSearch( bodyData ); + if ( entityData.success && entityData.data && entityData.data.response && entityData.data.response.length > 0 ) { + entityInformations = entityData.data.response; + } + } - if (!entityDetails.success || !entityDetails.data || !entityDetails.data.response || !entityDetails.data.response.length > 0) { + if ( locationCodes.length > 0 ) { + let bodyData = { + "code" : locationCodes + } + let entityData = await sunbirdUserProfile.learnerLocationSearch( bodyData ); + if ( entityData.success && entityData.data && entityData.data.response && entityData.data.response.length > 0 ) { + entityInformations = entityInformations.concat(entityData.data.response); + } + } + + if ( !entityInformations.length > 0 ) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND } } - - let entities = entityDetails.data.response; + let entityResult = []; //formating response - entities.map(entityData => { + entityInformations.map(entityData => { let data = {}; data._id = entityData.id; data.entityType = entityData.type; @@ -2514,7 +2537,7 @@ function _entitiesInformation(entityIds) { entitiesData = _entitiesMetaInformation(entityResult); } - + return resolve({ success: true, data: entitiesData @@ -2781,7 +2804,6 @@ function _observationDetails(observationData, userRoleAndProfileInformation = {} */ function _entitiesMetaInformation(entitiesData) { - entitiesData = entitiesData.map(entity => { entity.metaInformation._id = entity._id; entity.metaInformation.entityType = entity.entityType; From b0e92fbcb7d3575fbdf772bad43bf5a4ae506429 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 9 Aug 2022 09:26:00 +0530 Subject: [PATCH 155/373] user service variable change --- module/userProjects/helper.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index e6afa012..c1fc08bf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -23,7 +23,6 @@ const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); -const sunbirdUserProfile = require(GENERICS_FILES_PATH + "/services/users"); /** * UserProjectsHelper @@ -2693,7 +2692,7 @@ function _entitiesInformation(entityIds) { let bodyData = { "id" : locationIds } - let entityData = await sunbirdUserProfile.learnerLocationSearch( bodyData ); + let entityData = await userProfileService.learnerLocationSearch( bodyData ); if ( entityData.success && entityData.data && entityData.data.response && entityData.data.response.length > 0 ) { entityInformations = entityData.data.response; } @@ -2703,7 +2702,7 @@ function _entitiesInformation(entityIds) { let bodyData = { "code" : locationCodes } - let entityData = await sunbirdUserProfile.learnerLocationSearch( bodyData ); + let entityData = await userProfileService.learnerLocationSearch( bodyData ); if ( entityData.success && entityData.data && entityData.data.response && entityData.data.response.length > 0 ) { entityInformations = entityInformations.concat(entityData.data.response); } From 53f440010f50d1e77764ac5dcd360cefcb30b677 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 16 Aug 2022 14:51:43 +0530 Subject: [PATCH 156/373] review changes --- generics/services/users.js | 30 ++++++++++++++++-------------- module/userProjects/helper.js | 12 ++++++------ 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/generics/services/users.js b/generics/services/users.js index 8f325213..23057c0f 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -8,6 +8,7 @@ //dependencies const request = require('request'); const userServiceUrl = process.env.USER_SERVICE_URL; +const serverTimeout = CONSTANTS.common.SERVER_TIME_OUT; const profile = function ( token,userId = "" ) { return new Promise(async (resolve, reject) => { @@ -59,17 +60,16 @@ const profile = function ( token,userId = "" ) { }) } -const serverTimeout = process.env.SUNBIRD_SERVER_TIMEOUT ? parseInt( process.env.SUNBIRD_SERVER_TIMEOUT ) : 5000; + /** * * @function - * @name learnerLocationSearch - * @param {String} bearerToken - autherization token. + * @name locationSearch * @param {object} bodyData - bodydata . * @returns {Promise} returns a promise. */ -const learnerLocationSearch = function ( filterData ) { +const locationSearch = function ( filterData ) { return new Promise(async (resolve, reject) => { try { @@ -85,25 +85,27 @@ const learnerLocationSearch = function ( filterData ) { json : bodyData }; - request.post(url,options,learnerSearchCallback); + request.post(url,options,requestCallback); let result = { success : true }; - function learnerSearchCallback(err, data) { - - + function requestCallback(err, data) { if (err) { result.success = false; } else { - let response = data.body; - - if( response.responseCode === CONSTANTS.common.OK) { - result["data"] = response.result; + + if( response.responseCode === CONSTANTS.common.OK && + response.result && + response.result.response && + response.result.response.length > 0 + ) { + result["data"] = response.result.response; + result["count"] = response.result.count; } else { - result.success = false; + result.success = false; } } return resolve(result); @@ -122,5 +124,5 @@ const learnerLocationSearch = function ( filterData ) { } module.exports = { profile : profile, - learnerLocationSearch : learnerLocationSearch + locationSearch : locationSearch }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c1fc08bf..a481f135 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2692,9 +2692,9 @@ function _entitiesInformation(entityIds) { let bodyData = { "id" : locationIds } - let entityData = await userProfileService.learnerLocationSearch( bodyData ); - if ( entityData.success && entityData.data && entityData.data.response && entityData.data.response.length > 0 ) { - entityInformations = entityData.data.response; + let entityData = await userProfileService.locationSearch( bodyData ); + if ( entityData.success ) { + entityInformations = entityData.data; } } @@ -2702,9 +2702,9 @@ function _entitiesInformation(entityIds) { let bodyData = { "code" : locationCodes } - let entityData = await userProfileService.learnerLocationSearch( bodyData ); - if ( entityData.success && entityData.data && entityData.data.response && entityData.data.response.length > 0 ) { - entityInformations = entityInformations.concat(entityData.data.response); + let entityData = await userProfileService.locationSearch( bodyData ); + if ( entityData.success ) { + entityInformations = entityInformations.concat(entityData.data); } } From 7478444fba8eaa3dd6a61cfcf6fea17a89cd47e9 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 22 Aug 2022 18:18:19 +0530 Subject: [PATCH 157/373] service param change --- generics/services/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/services/users.js b/generics/services/users.js index 23057c0f..c19e9273 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -65,7 +65,7 @@ const profile = function ( token,userId = "" ) { * * @function * @name locationSearch - * @param {object} bodyData - bodydata . + * @param {object} filterData - location search filter object. * @returns {Promise} returns a promise. */ From 0b2478c21942b468d3cb66945512426bde5f28ab Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 23 Aug 2022 06:54:20 +0530 Subject: [PATCH 158/373] review change --- generics/helpers/cache.js | 62 ----------------------------------- generics/services/users.js | 31 ++++++++++++++---- module/reports/helper.js | 1 - module/userProjects/helper.js | 29 +++------------- 4 files changed, 30 insertions(+), 93 deletions(-) delete mode 100644 generics/helpers/cache.js diff --git a/generics/helpers/cache.js b/generics/helpers/cache.js deleted file mode 100644 index 603d1a29..00000000 --- a/generics/helpers/cache.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * name : cache.js - * author : Priyanka Pradeep - * created-date : 21-Feb-2020 - * Description : Cache set , get and remove functionality. - */ - - const nodeCache = require( "node-cache" ); - const cache = new nodeCache(); - - /** - * Get cache data. - * @method - * @name get - Get specific cache data - * @params key - name of the cache key. - * @returns {Array} - return specific cache data. -*/ - -function getValue(key){ - let data = []; - - if (cache.has(key)) { - data = cache.get(key); - } - - return data; -} - - - /** - * Set new cache data - * @method - * @name set - * @params key - name of the cache key. - * @params value - cache data to set. - * @returns {Array} - cache updated data. -*/ - -function setValue(key, value, timeout){ - let data = cache.set( key, value, timeout ); - return data; -} - -/** - * delete cache data - * @method - * @name remove - * @params key - cache key need to be removed. - * @returns -*/ - -function removeKey(key){ - - let data = cache.del(key); - return; -} - -module.exports = { - getValue : getValue, - setValue : setValue, - removeKey : removeKey -} \ No newline at end of file diff --git a/generics/services/users.js b/generics/services/users.js index c19e9273..c5e5a04d 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -8,7 +8,6 @@ //dependencies const request = require('request'); const userServiceUrl = process.env.USER_SERVICE_URL; -const serverTimeout = CONSTANTS.common.SERVER_TIME_OUT; const profile = function ( token,userId = "" ) { return new Promise(async (resolve, reject) => { @@ -66,10 +65,11 @@ const profile = function ( token,userId = "" ) { * @function * @name locationSearch * @param {object} filterData - location search filter object. + * @param {Boolean} formatResult - format result or not. * @returns {Promise} returns a promise. */ -const locationSearch = function ( filterData ) { +const locationSearch = function ( filterData, formatResult = false ) { return new Promise(async (resolve, reject) => { try { @@ -86,7 +86,7 @@ const locationSearch = function ( filterData ) { }; request.post(url,options,requestCallback); - + let result = { success : true }; @@ -102,8 +102,27 @@ const locationSearch = function ( filterData ) { response.result.response && response.result.response.length > 0 ) { - result["data"] = response.result.response; - result["count"] = response.result.count; + if ( formatResult ) { + let entityResult =new Array; + response.result.response.map(entityData => { + let data = {}; + data._id = entityData.id; + data.entityType = entityData.type; + data.metaInformation = {}; + data.metaInformation.name = entityData.name; + data.metaInformation.externalId = entityData.code + data.registryDetails = {}; + data.registryDetails.locationId = entityData.id; + data.registryDetails.code = entityData.code; + entityResult.push(data); + }); + result["data"] = entityResult; + result["count"] = response.result.count; + } else { + result["data"] = response.result.response; + result["count"] = response.result.count; + } + } else { result.success = false; } @@ -115,7 +134,7 @@ const locationSearch = function ( filterData ) { return resolve (result = { success : false }); - }, serverTimeout); + }, CONSTANTS.common.SERVER_TIME_OUT); } catch (error) { return reject(error); diff --git a/module/reports/helper.js b/module/reports/helper.js index 144a5f24..a07f2ec5 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -320,7 +320,6 @@ module.exports = class ReportsHelper { } } catch (error) { - console.log("error : ",error) return resolve({ success: false, diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index a481f135..de6e4b76 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2692,7 +2692,7 @@ function _entitiesInformation(entityIds) { let bodyData = { "id" : locationIds } - let entityData = await userProfileService.locationSearch( bodyData ); + let entityData = await userProfileService.locationSearch( bodyData, formatResult = true); if ( entityData.success ) { entityInformations = entityData.data; } @@ -2702,7 +2702,7 @@ function _entitiesInformation(entityIds) { let bodyData = { "code" : locationCodes } - let entityData = await userProfileService.locationSearch( bodyData ); + let entityData = await userProfileService.locationSearch( bodyData , formatResult = true ); if ( entityData.success ) { entityInformations = entityInformations.concat(entityData.data); } @@ -2714,30 +2714,11 @@ function _entitiesInformation(entityIds) { message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND } } - - let entityResult = []; - //formating response - entityInformations.map(entityData => { - let data = {}; - data._id = entityData.id; - data.entityType = entityData.type; - data.metaInformation = {}; - data.metaInformation.name = entityData.name; - data.metaInformation.externalId = entityData.code - data.registryDetails = {}; - data.registryDetails.locationId = entityData.id; - data.registryDetails.code = entityData.code; - entityResult.push(data); - }); - - let entitiesData = []; - - if ( entityResult.length > 0 ) { - - entitiesData = _entitiesMetaInformation(entityResult); + if ( entityInformations.length > 0 ) { + entitiesData = _entitiesMetaInformation(entityInformations); } - + return resolve({ success: true, data: entitiesData From 57b9e4d200c60d9e873c13819121105eca6a4fac Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 2 Sep 2022 15:37:34 +0530 Subject: [PATCH 159/373] hierarchy added --- generics/services/users.js | 40 ++++++++++++++++++++++++++++-- models/programs.js | 1 - models/project-templates.js | 3 --- models/solutions.js | 2 -- module/project/templates/helper.js | 1 - module/userProjects/helper.js | 25 +++++++++++-------- 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/generics/services/users.js b/generics/services/users.js index c5e5a04d..a44f052f 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -80,7 +80,7 @@ const locationSearch = function ( filterData, formatResult = false ) { userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; const options = { headers : { - "content-type": "application/json" + "content-type": "application/json", }, json : bodyData }; @@ -141,7 +141,43 @@ const locationSearch = function ( filterData, formatResult = false ) { } }) } +/** + * get Parent Entities of an entity. + * @method + * @name getParentEntities + * @param {String} entityId - entity id + * @returns {Array} - parent entities. +*/ + +async function getParentEntities( entityId, iteration = 0, parentEntities ) { + + if ( iteration == 0 ) { + parentEntities = []; + } + + let filterQuery = { + "id" : entityId + }; + + let entityDetails = await locationSearch(filterQuery); + if ( !entityDetails.success ) { + return parentEntities; + } else { + + let entityData = entityDetails.data[0]; + if ( iteration > 0 ) parentEntities.push(entityData); + if ( entityData.parentId ) { + iteration = iteration + 1; + entityId = entityData.parentId; + await getParentEntities(entityId, iteration, parentEntities); + } + } + + return parentEntities; + +} module.exports = { profile : profile, - locationSearch : locationSearch + locationSearch : locationSearch, + getParentEntities : getParentEntities }; diff --git a/models/programs.js b/models/programs.js index 67b6a227..cb411bb3 100644 --- a/models/programs.js +++ b/models/programs.js @@ -29,7 +29,6 @@ module.exports = { }, scope : { entityType : String, - entityTypeId : "ObjectId", entities : { type : Array, index : true diff --git a/models/project-templates.js b/models/project-templates.js index 45d1604e..4960c60d 100644 --- a/models/project-templates.js +++ b/models/project-templates.js @@ -75,9 +75,6 @@ module.exports = { entityType : { type : String }, - entityTypeId : { - type : "ObjectId" - }, taskSequence : { type : Array, default : [] diff --git a/models/solutions.js b/models/solutions.js index 4e3c4c9f..c55a0508 100644 --- a/models/solutions.js +++ b/models/solutions.js @@ -22,7 +22,6 @@ module.exports = { themes: Array, flattenedThemes : Array, questionSequenceByEcm: Object, - entityTypeId: "ObjectId", entityType: String, type: String, subType: String, @@ -74,7 +73,6 @@ module.exports = { referenceFrom : String, scope : { entityType : String, - entityTypeId : "ObjectId", entities : { type : Array, index : true diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 877880b1..51bdcaef 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -219,7 +219,6 @@ module.exports = class ProjectTemplatesHelper { if( parsedData.entityType && parsedData.entityType !== "" ) { parsedData.entityType = csvInformation.entityTypes[parsedData.entityType].name; - parsedData.entityTypeId = csvInformation.entityTypes[parsedData.entityType]._id; } let learningResources = diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index de6e4b76..65106c60 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1194,7 +1194,7 @@ module.exports = class UserProjectsHelper { return resolve(entityInformation); } - projectCreation.data["entityInformation"] = _entitiesMetaInformation( + projectCreation.data["entityInformation"] = await _entitiesMetaInformation( entityInformation.data )[0]; @@ -2716,9 +2716,9 @@ function _entitiesInformation(entityIds) { } let entitiesData = []; if ( entityInformations.length > 0 ) { - entitiesData = _entitiesMetaInformation(entityInformations); + entitiesData = await _entitiesMetaInformation(entityInformations); } - + return resolve({ success: true, data: entitiesData @@ -2985,13 +2985,18 @@ function _observationDetails(observationData, userRoleAndProfileInformation = {} */ function _entitiesMetaInformation(entitiesData) { - entitiesData = entitiesData.map(entity => { - entity.metaInformation._id = entity._id; - entity.metaInformation.entityType = entity.entityType; - entity.metaInformation.registryDetails = entity.registryDetails; - return entity.metaInformation; - }); - return entitiesData; + return new Promise(async (resolve, reject) => { + let entityInformation = [] + for ( let index = 0; index < entitiesData.length; index++ ) { + let entityHierarchy = await userProfileService.getParentEntities( entitiesData[index]._id ); + entitiesData[index].metaInformation.hierarchy = entityHierarchy; + entitiesData[index].metaInformation._id = entitiesData[index]._id; + entitiesData[index].metaInformation.entityType = entitiesData[index].entityType; + entitiesData[index].metaInformation.registryDetails = entitiesData[index].registryDetails; + entityInformation.push(entitiesData[index].metaInformation) + } + return resolve (entityInformation); + }) } From 179ce152d5c13ae49f6ebd97711cf019e0d12611 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 2 Sep 2022 15:51:09 +0530 Subject: [PATCH 160/373] comma removed --- generics/services/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/services/users.js b/generics/services/users.js index a44f052f..53f8edae 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -80,7 +80,7 @@ const locationSearch = function ( filterData, formatResult = false ) { userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; const options = { headers : { - "content-type": "application/json", + "content-type": "application/json" }, json : bodyData }; From 404744a4eb4e9456e061c47d608afe9b69926f68 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 6 Sep 2022 17:22:33 +0530 Subject: [PATCH 161/373] env variable function change --- envVariables.js | 88 ++++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/envVariables.js b/envVariables.js index 9ccd9f9f..8ce15ac4 100644 --- a/envVariables.js +++ b/envVariables.js @@ -48,53 +48,66 @@ module.exports = function() { Object.keys(enviromentVariables).forEach(eachEnvironmentVariable=>{ let tableObj = { - [eachEnvironmentVariable] : "" + [eachEnvironmentVariable] : "PASSED" }; + + let keyCheckPass = true; + - if( - enviromentVariables[eachEnvironmentVariable].requiredIf - && process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] - && process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] === enviromentVariables[eachEnvironmentVariable].requiredIf.value - ) { - tableObj[eachEnvironmentVariable].optional = false; + if(enviromentVariables[eachEnvironmentVariable].optional === true + && enviromentVariables[eachEnvironmentVariable].requiredIf + && enviromentVariables[eachEnvironmentVariable].requiredIf.key + && enviromentVariables[eachEnvironmentVariable].requiredIf.key != "" + && enviromentVariables[eachEnvironmentVariable].requiredIf.operator + && validRequiredIfOperators.includes(enviromentVariables[eachEnvironmentVariable].requiredIf.operator) + && enviromentVariables[eachEnvironmentVariable].requiredIf.value + && enviromentVariables[eachEnvironmentVariable].requiredIf.value != "") { + switch (enviromentVariables[eachEnvironmentVariable].requiredIf.operator) { + case "EQUALS": + if(process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] === enviromentVariables[eachEnvironmentVariable].requiredIf.value) { + enviromentVariables[eachEnvironmentVariable].optional = false; + } + break; + case "NOT_EQUALS": + if(process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] != enviromentVariables[eachEnvironmentVariable].requiredIf.value) { + enviromentVariables[eachEnvironmentVariable].optional = false; + } + break; + default: + break; + } } - - if( - !(process.env[eachEnvironmentVariable]) && - !(enviromentVariables[eachEnvironmentVariable].optional) - ) { - success = false; - - if( - enviromentVariables[eachEnvironmentVariable].default && - enviromentVariables[eachEnvironmentVariable].default != "" - ) { - process.env[eachEnvironmentVariable] = - enviromentVariables[eachEnvironmentVariable].default; + if(enviromentVariables[eachEnvironmentVariable].optional === false) { + if(!(process.env[eachEnvironmentVariable]) + || process.env[eachEnvironmentVariable] == "") { + success = false; + keyCheckPass = false; + } else if (enviromentVariables[eachEnvironmentVariable].possibleValues + && Array.isArray(enviromentVariables[eachEnvironmentVariable].possibleValues) + && enviromentVariables[eachEnvironmentVariable].possibleValues.length > 0) { + if(!enviromentVariables[eachEnvironmentVariable].possibleValues.includes(process.env[eachEnvironmentVariable])) { + success = false; + keyCheckPass = false; + enviromentVariables[eachEnvironmentVariable].message += ` Valid values - ${enviromentVariables[eachEnvironmentVariable].possibleValues.join(", ")}` + } } + } + + if((!(process.env[eachEnvironmentVariable]) + || process.env[eachEnvironmentVariable] == "") + && enviromentVariables[eachEnvironmentVariable].default + && enviromentVariables[eachEnvironmentVariable].default != "") { + process.env[eachEnvironmentVariable] = enviromentVariables[eachEnvironmentVariable].default; + } - if( - enviromentVariables[eachEnvironmentVariable] && - enviromentVariables[eachEnvironmentVariable].message !== "" - ) { + if(!keyCheckPass) { + if(enviromentVariables[eachEnvironmentVariable].message !== "") { tableObj[eachEnvironmentVariable] = enviromentVariables[eachEnvironmentVariable].message; } else { - tableObj[eachEnvironmentVariable] = "required"; + tableObj[eachEnvironmentVariable] = `FAILED - ${eachEnvironmentVariable} is required`; } - - } else { - - tableObj[eachEnvironmentVariable] = "Passed"; - - if( - enviromentVariables[eachEnvironmentVariable].possibleValues && - !enviromentVariables[eachEnvironmentVariable].possibleValues.includes(process.env[eachEnvironmentVariable]) - ) { - tableObj[eachEnvironmentVariable] = ` Valid values - ${enviromentVariables[eachEnvironmentVariable].possibleValues.join(", ")}`; - } - } tableData.push(tableObj); @@ -108,3 +121,4 @@ module.exports = function() { } + From c766bbad3d3f2e6b73a70b0ad7039781965aec3e Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Mon, 12 Sep 2022 12:48:06 +0530 Subject: [PATCH 162/373] removed solution update from solutionDetails api & added project template info in solution --- generics/constants/common.js | 3 ++- module/project/templateTasks/helper.js | 25 +++++++++++++++++++++++++ module/userProjects/helper.js | 17 ----------------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/generics/constants/common.js b/generics/constants/common.js index 0884d1e0..dd75260a 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -49,5 +49,6 @@ module.exports = { "IMAGE_DATA_TYPE" : "image/jpeg", "DISTRICT": "district", "SERVER_TIME_OUT" : 5000, - "OK" : "OK" + "OK" : "OK", + "PROJECT" : "project" }; diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 082b4777..615cc938 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -16,6 +16,7 @@ const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/ const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); +const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); module.exports = class ProjectTemplateTasksHelper { @@ -376,6 +377,30 @@ module.exports = class ProjectTemplateTasksHelper { } } + //update solution project key + if ( taskData.type == CONSTANTS.common.OBSERVATION && + taskData.solutionDetails && + taskData.solutionDetails._id + ) { + + let updateSolutionObj = { + "$set" : {} + }; + + updateSolutionObj["$set"]["referenceFrom"] = CONSTANTS.common.PROJECT; + updateSolutionObj["$set"]["project"] = { + _id: template._id.toString(), + taskId: taskData._id.toString() + }; + + await solutionsQueries.updateSolutionDocument + ( + { _id : taskData.solutionDetails._id }, + updateSolutionObj + ) + } + + //update project template await projectTemplateQueries.updateProjectTemplateDocument ( { _id : template._id }, diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 65106c60..0bbeb877 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2914,23 +2914,6 @@ function _observationDetails(observationData, userRoleAndProfileInformation = {} } else { - let solutionUpdated = - await surveyService.updateSolution( - observationData.token, - { - project: observationData.project, - referenceFrom: "project" - }, - observationData.solutionDetails.externalId - ); - - if (!solutionUpdated.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.SOLUTION_NOT_UPDATED - } - } - let startDate = new Date(); let endDate = new Date(); endDate.setFullYear(endDate.getFullYear() + 1); From 7c9c87fdf1ee7c1bed29083a11c00a1e5ba82a0e Mon Sep 17 00:00:00 2001 From: Priyanka Pradeep Date: Tue, 13 Sep 2022 14:51:08 +0530 Subject: [PATCH 163/373] entityInformation fix in project --- module/userProjects/helper.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 0bbeb877..383daaee 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1180,7 +1180,7 @@ module.exports = class UserProjectsHelper { if( bodyData.role ) { projectCreation.data["userRole"] = bodyData.role; } - + if( solutionDetails.entityType && bodyData[solutionDetails.entityType] ) { @@ -1189,14 +1189,18 @@ module.exports = class UserProjectsHelper { userToken, [bodyData[solutionDetails.entityType]] ); - + if( !entityInformation.success ) { return resolve(entityInformation); } - - projectCreation.data["entityInformation"] = await _entitiesMetaInformation( + + let entityDetails = await _entitiesMetaInformation( entityInformation.data - )[0]; + ); + + if ( entityDetails && entityDetails.length > 0 ) { + projectCreation.data["entityInformation"] = entityDetails[0]; + } projectCreation.data.entityId = entityInformation.data[0]._id; } @@ -2113,7 +2117,7 @@ module.exports = class UserProjectsHelper { libraryProjects.data.entityId = entityInformation.data[0]._id; } - if( requestedData.solutionId && requestedData.solutionId !== "" && isATargetedSolution === false){ + if( requestedData.solutionId && requestedData.solutionId !== "" && isATargetedSolution === false ){ let programAndSolutionInformation = await this.createProgramAndSolution( @@ -2168,8 +2172,8 @@ module.exports = class UserProjectsHelper { libraryProjects.data, programAndSolutionInformation.data ) - } + //Fetch user profile information by calling sunbird's user read api. let addReportInfoToSolution = false; let userProfile = await userProfileService.profile(userToken, userId); @@ -2978,6 +2982,7 @@ function _entitiesMetaInformation(entitiesData) { entitiesData[index].metaInformation.registryDetails = entitiesData[index].registryDetails; entityInformation.push(entitiesData[index].metaInformation) } + return resolve (entityInformation); }) } From dda4f8d4463553a5925b5ca3c3bc8276ef21271c Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 23 Sep 2022 17:02:23 +0530 Subject: [PATCH 164/373] Entitytype validation removed from extractCsvInformation --- module/project/templates/helper.js | 66 +++++++++++++++--------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 51bdcaef..8b07d62d 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -41,7 +41,8 @@ module.exports = class ProjectTemplatesHelper { let categoryIds = []; let roleIds = []; let tasksIds = []; - let entityTypes = []; + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // let entityTypes = []; csvData.forEach(template=>{ @@ -69,10 +70,10 @@ module.exports = class ProjectTemplatesHelper { parsedData.recommendedFor ); } - - if( parsedData.entityType ) { - entityTypes.push(parsedData.entityType); - } + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // if( parsedData.entityType ) { + // entityTypes.push(parsedData.entityType); + // } }); @@ -126,37 +127,38 @@ module.exports = class ProjectTemplatesHelper { } }),{}); } + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // let entityTypesData = {}; - let entityTypesData = {}; - - if( entityTypes.length > 0 ) { + // if( entityTypes.length > 0 ) { - let entityTypesDocument = - await coreService.entityTypesDocuments(); - - if( !entityTypesDocument.success ) { - throw { - message : CONSTANTS.apiResponses.ENTITY_TYPES_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - entityTypesData = entityTypesDocument.data.reduce((ac,entityType)=> ({ - ...ac, - [entityType.name] : { - _id : ObjectId(entityType._id), - name : entityType.name - } - }),{}); - - } + // let entityTypesDocument = + // await coreService.entityTypesDocuments(); + + // if( !entityTypesDocument.success ) { + // throw { + // message : CONSTANTS.apiResponses.ENTITY_TYPES_NOT_FOUND, + // status : HTTP_STATUS_CODE['bad_request'].status + // } + // } + + // entityTypesData = entityTypesDocument.data.reduce((ac,entityType)=> ({ + // ...ac, + // [entityType.name] : { + // _id : ObjectId(entityType._id), + // name : entityType.name + // } + // }),{}); + + // } return resolve({ success : true, data : { categories : categoriesData, roles : recommendedFor, - entityTypes : entityTypesData + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // entityTypes : entityTypesData } }); @@ -216,10 +218,10 @@ module.exports = class ProjectTemplatesHelper { } parsedData.recommendedFor = recommendedFor; - - if( parsedData.entityType && parsedData.entityType !== "" ) { - parsedData.entityType = csvInformation.entityTypes[parsedData.entityType].name; - } + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // if( parsedData.entityType && parsedData.entityType !== "" ) { + // parsedData.entityType = csvInformation.entityTypes[parsedData.entityType].name; + // } let learningResources = await learningResourcesHelper.extractLearningResourcesFromCsv(parsedData); From 67b9cd1eb477701bbe9572eac62b4bb2e8e2f39b Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 3 Oct 2022 21:47:47 +0530 Subject: [PATCH 165/373] certificate template mapped to solution and project --- config/globals.js | 1 + controllers/v1/certificateTemplates.js | 16 ++++++ databaseQueries/certificateTemplates.js | 60 ++++++++++++++++++++++ models/certificateTemplates.js | 14 ++++++ models/projects.js | 13 ++++- module/library/categories/helper.js | 4 +- module/project/templates/helper.js | 2 +- module/userProjects/helper.js | 67 +++++++++++++++++++------ 8 files changed, 159 insertions(+), 18 deletions(-) create mode 100644 controllers/v1/certificateTemplates.js create mode 100644 databaseQueries/certificateTemplates.js create mode 100644 models/certificateTemplates.js diff --git a/config/globals.js b/config/globals.js index ad63ab7a..c14c6428 100644 --- a/config/globals.js +++ b/config/globals.js @@ -76,6 +76,7 @@ module.exports = function () { global.schemas[name] = require(PROJECT_ROOT_DIRECTORY + '/models/' + file); } }); + // All controllers global.controllers = requireAll({ diff --git a/controllers/v1/certificateTemplates.js b/controllers/v1/certificateTemplates.js new file mode 100644 index 00000000..c57fa739 --- /dev/null +++ b/controllers/v1/certificateTemplates.js @@ -0,0 +1,16 @@ +/** + * name : certificateTemplates.js + * author : Vishnu + * created-date : 29-Sep-2022 + * Description : Certificate template related information. +*/ + +module.exports = class CertificateTemplates extends Abstract { + constructor() { + super("certificateTemplates"); + } + + static get name() { + return "certificateTemplates"; + } +} \ No newline at end of file diff --git a/databaseQueries/certificateTemplates.js b/databaseQueries/certificateTemplates.js new file mode 100644 index 00000000..fa2a2ddc --- /dev/null +++ b/databaseQueries/certificateTemplates.js @@ -0,0 +1,60 @@ +/** + * name : certificateTemplates.js + * author : Vishnu + * created-date : 03-Oct-2022 + * Description : Certificate template helper for DB interactions. + */ + +// Dependencies + +/** + * CertificateTemplates + * @class +*/ + +module.exports= class CertificateTemplates{ + /** + * certificate template details. + * @method + * @name certificateTemplateDocument + * @param {Array} [filterData = "all"] - certificate template filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} certificateTemplates details. + */ + + static certificateTemplateDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + let certificateTemplateDoc = + await database.models.certificateTemplates.find( + queryObject, + projection + ).lean(); + + return resolve(certificateTemplateDoc); + + } catch (error) { + return reject(error); + } + }); + } +} \ No newline at end of file diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js new file mode 100644 index 00000000..d2f9f855 --- /dev/null +++ b/models/certificateTemplates.js @@ -0,0 +1,14 @@ +module.exports = { + name: "certificateTemplates", + schema: { + templateUrl: { + type : String, + index : true + }, + issuer: Object, + status: String, + solutionId: "ObjectId", + programId: "ObjectId", + criteria: Object + } +}; \ No newline at end of file diff --git a/models/projects.js b/models/projects.js index c9c2a1a6..64d95dc4 100644 --- a/models/projects.js +++ b/models/projects.js @@ -135,7 +135,18 @@ module.exports = { default : [] }, remarks : String, - userProfile : Object + userProfile : Object, + certificate : { + templateId : "ObjectId", + osid : String, + transactionId : String, + templateUrl : String, + status : String, + eligible : Boolean, + message : String, + issuedOn : Date, + criteria : Object + } }, compoundIndex: [ { diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index dd732aa4..f69ed22c 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -198,7 +198,7 @@ module.exports = class LibraryCategoriesHelper { message : CONSTANTS.apiResponses.PROJECT_NOT_FOUND, }; } - + projectsData[0].showProgramAndEntity = false; if( projectsData[0].tasks && projectsData[0].tasks.length > 0 ) { @@ -259,7 +259,7 @@ module.exports = class LibraryCategoriesHelper { data : projectsData[0] }); - } catch (error) { + } catch (error) { return resolve({ status : error.status ? error.status : HTTP_STATUS_CODE['internal_server_error'].status, success: false, diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 8b07d62d..72d7d7b5 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -557,7 +557,7 @@ module.exports = class ProjectTemplatesHelper { externalId : templateId, isReusable : true }); - + if ( !projectTemplateData.length > 0 ) { throw new Error(CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND) } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 383daaee..74b7a588 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -23,6 +23,7 @@ const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); +const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); /** * UserProjectsHelper @@ -454,9 +455,9 @@ module.exports = class UserProjectsHelper { result.solutionInformation = _.pick( solutionAndProgramCreation.data.solution, - ["name", "externalId", "description", "_id", "entityType"] + ["name", "externalId", "description", "_id", "entityType", "certificateTemplateId"] ); - + result.solutionInformation._id = ObjectId(result.solutionInformation._id); @@ -1157,7 +1158,24 @@ module.exports = class UserProjectsHelper { if( appVersion !== "" ) { projectCreation.data["appInformation"]["appVersion"] = appVersion; } - + + if ( solutionDetails.certificateTemplateId && solutionDetails.certificateTemplateId !== "" ) { + // <- Add certificate template details to projectCreation data if present -> + const certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : solutionDetails.certificateTemplateId + }); + + // create certificate object and add data if certificate template is present. + if ( certificateTemplateDetails.length > 0 ) { + projectCreation.data["certificate"] = { + templateId : certificateTemplateDetails[0]._id, + templateUrl : certificateTemplateDetails[0].templateUrl, + status : certificateTemplateDetails[0].status ? certificateTemplateDetails[0].status : "", + criteria : certificateTemplateDetails[0].criteria ? certificateTemplateDetails[0].criteria : "", + } + } + } + let getUserProfileFromObservation = false; if( bodyData && Object.keys(bodyData).length > 0 ) { @@ -2061,7 +2079,6 @@ module.exports = class UserProjectsHelper { isATargetedSolution ); - if ( libraryProjects.data && !Object.keys(libraryProjects.data).length > 0 @@ -2173,7 +2190,29 @@ module.exports = class UserProjectsHelper { programAndSolutionInformation.data ) } - + // <- Add certificate template data + if ( + libraryProjects.data.solutionInformation && + libraryProjects.data.solutionInformation.certificateTemplateId && + libraryProjects.data.solutionInformation.certificateTemplateId !== "" + ){ + // <- Add certificate template details to projectCreation data if present -> + const certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : libraryProjects.data.solutionInformation.certificateTemplateId + }); + + // create certificate object and add data if certificate template is present. + if ( certificateTemplateDetails.length > 0 ) { + libraryProjects.data["certificate"] = { + templateId : certificateTemplateDetails[0]._id, + templateUrl : certificateTemplateDetails[0].templateUrl, + status : certificateTemplateDetails[0].status ? certificateTemplateDetails[0].status : "", + criteria : certificateTemplateDetails[0].criteria ? certificateTemplateDetails[0].criteria : "", + } + } + delete libraryProjects.data.solutionInformation.certificateTemplateId; + } + //Fetch user profile information by calling sunbird's user read api. let addReportInfoToSolution = false; let userProfile = await userProfileService.profile(userToken, userId); @@ -2199,11 +2238,11 @@ module.exports = class UserProjectsHelper { libraryProjects.data.projectTemplateId = libraryProjects.data._id; libraryProjects.data.projectTemplateExternalId = libraryProjects.data.externalId; - + let projectCreation = await database.models.projects.create( _.omit(libraryProjects.data, ["_id"]) ); - + if ( addReportInfoToSolution && projectCreation._doc.solutionId ) { let updateSolution = await solutionsHelper.addReportInformationInSolution( @@ -2221,9 +2260,9 @@ module.exports = class UserProjectsHelper { userToken ); } - + projectCreation = await _projectInformation(projectCreation._doc); - + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECTS_FETCHED, @@ -2294,7 +2333,7 @@ function _projectInformation(project) { return new Promise(async (resolve, reject) => { try { - + if (project.entityInformation) { project.entityId = project.entityInformation._id; project.entityName = project.entityInformation.name; @@ -2304,7 +2343,7 @@ function _projectInformation(project) { project.programId = project.programInformation._id; project.programName = project.programInformation.name; } - + //project attachments if ( project.attachments && project.attachments.length > 0 ) { @@ -2331,7 +2370,7 @@ function _projectInformation(project) { } } - + //task attachments if (project.tasks && project.tasks.length > 0) { //order task based on task sequence @@ -2378,7 +2417,7 @@ function _projectInformation(project) { project.tasks = taskAttachmentsUrl.data; } } - + project.status = project.status ? project.status : CONSTANTS.common.NOT_STARTED_STATUS; @@ -2393,7 +2432,7 @@ function _projectInformation(project) { delete project.entityInformation; delete project.solutionInformation; delete project.programInformation; - + return resolve({ success: true, data: project From e6fea80bccdad4c98fbd6f857483fc5c6c73389f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 6 Oct 2022 11:54:14 +0530 Subject: [PATCH 166/373] certificate template schema updated --- models/certificateTemplates.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index d2f9f855..b9a1541e 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -1,14 +1,14 @@ module.exports = { - name: "certificateTemplates", - schema: { - templateUrl: { - type : String, - index : true - }, - issuer: Object, - status: String, - solutionId: "ObjectId", - programId: "ObjectId", - criteria: Object - } + name: "certificateTemplates", + schema: { + templateUrl: String, + issuer: Object, + status: String, + solutionId: { + type : "ObjectId", + index : true + }, + programId: "ObjectId", + criteria: Object + } }; \ No newline at end of file From 127cd21fe8219997b2fb100ac56c99b959d6058d Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 6 Oct 2022 13:46:06 +0530 Subject: [PATCH 167/373] certificate template model changes --- models/certificateTemplates.js | 10 ++++++++-- module/userProjects/helper.js | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index b9a1541e..40b55e56 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -3,12 +3,18 @@ module.exports = { schema: { templateUrl: String, issuer: Object, - status: String, + status: { + type : String, + required : true + }, solutionId: { type : "ObjectId", index : true }, programId: "ObjectId", - criteria: Object + criteria: { + type : Object, + required : true + } } }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 74b7a588..54c86770 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1170,8 +1170,8 @@ module.exports = class UserProjectsHelper { projectCreation.data["certificate"] = { templateId : certificateTemplateDetails[0]._id, templateUrl : certificateTemplateDetails[0].templateUrl, - status : certificateTemplateDetails[0].status ? certificateTemplateDetails[0].status : "", - criteria : certificateTemplateDetails[0].criteria ? certificateTemplateDetails[0].criteria : "", + status : certificateTemplateDetails[0].status, + criteria : certificateTemplateDetails[0].criteria, } } } @@ -2206,8 +2206,8 @@ module.exports = class UserProjectsHelper { libraryProjects.data["certificate"] = { templateId : certificateTemplateDetails[0]._id, templateUrl : certificateTemplateDetails[0].templateUrl, - status : certificateTemplateDetails[0].status ? certificateTemplateDetails[0].status : "", - criteria : certificateTemplateDetails[0].criteria ? certificateTemplateDetails[0].criteria : "", + status : certificateTemplateDetails[0].status, + criteria : certificateTemplateDetails[0].criteria, } } delete libraryProjects.data.solutionInformation.certificateTemplateId; From c53a23da9e7f0974a22f7f3f007391cd192c6311 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 7 Oct 2022 09:27:34 +0530 Subject: [PATCH 168/373] templateUrl property change --- models/certificateTemplates.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index 40b55e56..8f8dfaf3 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -1,7 +1,10 @@ module.exports = { name: "certificateTemplates", schema: { - templateUrl: String, + templateUrl: { + type : String, + required : true + }, issuer: Object, status: { type : String, From 67e9afcc537454556c09c92e937f65a2658066f3 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 7 Oct 2022 13:47:14 +0530 Subject: [PATCH 169/373] made templateUrl required false --- models/certificateTemplates.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index 8f8dfaf3..40b55e56 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -1,10 +1,7 @@ module.exports = { name: "certificateTemplates", schema: { - templateUrl: { - type : String, - required : true - }, + templateUrl: String, issuer: Object, status: { type : String, From ac02cad3bbe8f69ef83a44230337565397789d13 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 13 Oct 2022 09:14:35 +0530 Subject: [PATCH 170/373] kafka consumer added to existing topic --- config/kafka.js | 14 +++++ .../kafka/consumers/certificateSubmissions.js | 61 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 generics/kafka/consumers/certificateSubmissions.js diff --git a/config/kafka.js b/config/kafka.js index 3d248170..23cdfbc8 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -9,6 +9,7 @@ //dependencies const kafka = require('kafka-node'); const SUBMISSION_TOPIC = process.env.SUBMISSION_TOPIC; +const CERTIFICATE_TOPIC = process.env.PROJECT_SUBMISSION_TOPIC; /** * Kafka configurations. @@ -44,6 +45,12 @@ const connect = function() { process.env.KAFKA_URL ); + // project certificate details consumer + _sendToKafkaConsumers( + CERTIFICATE_TOPIC, + process.env.KAFKA_URL + ); + return { kafkaProducer: producer, kafkaClient: client @@ -82,6 +89,10 @@ var _sendToKafkaConsumers = function (topic,host) { if (message && message.topic === SUBMISSION_TOPIC) { submissionsConsumer.messageReceived(message); } + // call certificateSubmissionsConsumer + if (message && message.topic === CERTIFICATE_TOPIC) { + certificateSubmissionsConsumer.messageReceived(message); + } }); @@ -90,6 +101,9 @@ var _sendToKafkaConsumers = function (topic,host) { if(error.topics && error.topics[0] === SUBMISSION_TOPIC) { submissionsConsumer.errorTriggered(error); } + if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { + certificateSubmissionsConsumer.errorTriggered(error); + } }); diff --git a/generics/kafka/consumers/certificateSubmissions.js b/generics/kafka/consumers/certificateSubmissions.js new file mode 100644 index 00000000..bca98ab2 --- /dev/null +++ b/generics/kafka/consumers/certificateSubmissions.js @@ -0,0 +1,61 @@ +/** + * name : certificateSubmissions.js + * author : Vishnu + * created-date : 10-Oct-2022 + * Description : Project certificates submission consumer. +*/ + +//dependencies +const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); + +/** + * submission consumer message received. + * @function + * @name messageReceived + * @param {String} message - consumer data + * @returns {Promise} return a Promise. +*/ + +var messageReceived = function (message) { + + return new Promise(async function (resolve, reject) { + + try { + // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. + let parsedMessage = JSON.parse(message.value); + if ( parsedMessage.status == CONSTANTS.common.SUBMITTED_STATUS && parsedMessage.certificate ) { + await userProjectsHelper.generateCertificate(parsedMessage); + } + return resolve("Message Received"); + } catch (error) { + return reject(error); + } + + }); +}; + +/** + * If message is not received. + * @function + * @name errorTriggered + * @param {Object} error - error object + * @returns {Promise} return a Promise. +*/ + +var errorTriggered = function (error) { + + return new Promise(function (resolve, reject) { + + try { + return resolve(error); + } catch (error) { + return reject(error); + } + + }); +}; + +module.exports = { + messageReceived: messageReceived, + errorTriggered: errorTriggered +}; From f981d216d3d86b8d7bf181c19146c8025722870d Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 13 Oct 2022 13:47:33 +0530 Subject: [PATCH 171/373] generics, model and validation --- generics/constants/api-responses.js | 4 +++- generics/constants/common.js | 4 +++- generics/constants/endpoints.js | 4 +++- generics/helpers/utils.js | 15 ++++++++++++++- models/projects.js | 5 ++++- module/userProjects/validator/v1.js | 3 +++ 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 9b85a71f..bd0c1d6a 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -124,5 +124,7 @@ module.exports = { "TEMPLATE_ID_OR_LINK_REQUIRED" : "TemplateId or Link either one is required", "TEMPLATE_ID_NOT_FOUND_IN_SOLUTION" : "Could not found templateId in solution", "FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED" : "Failed to sync, Project is already Submitted", - "SOLUTION_ID_AND_USERPROFILE_REQUIRED": "Required solution Id and userProfile" + "SOLUTION_ID_AND_USERPROFILE_REQUIRED": "Required solution Id and userProfile", + "PROJECT_WITH_CERTIFICATE_NOT_FOUND": "No certification project found for user", + "PROJECT_CERTIFICATE_GENERATED" : "Successfully generated project certificate" }; diff --git a/generics/constants/common.js b/generics/constants/common.js index dd75260a..ecc4ba61 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -50,5 +50,7 @@ module.exports = { "DISTRICT": "district", "SERVER_TIME_OUT" : 5000, "OK" : "OK", - "PROJECT" : "project" + "PROJECT" : "project", + "PROJECT_CERTIFICATE_RECIPIENT_TYPE" : "user", + "PROJECT_CERTIFICATE_GENERATED" : "Certificate generated successfully" }; diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 11c43bb4..5cde94a3 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -47,5 +47,7 @@ module.exports = { FILES_DOWNLOADABLE_URL: "/v1/cloud-services/files/getDownloadableUrl", OBSERVATION_DETAILS : "/v1/observations/details", USER_READ_V5 : "/v5/user/read", - GET_LOCATION_DATA : "/v1/location/search" + GET_LOCATION_DATA : "/v1/location/search", + CERTIFICATE_CREATE : "/api/v1/ProjectCertificate", + CERTIFICATE_API_CALLBACK : "/api/userProject/mlproject/v1/certificateCallback" }; diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 58d92e77..b4b1f62c 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -264,6 +264,18 @@ function checkValidUUID(uuids) { } return validateUUID; } + +/** + * convert string to upperCase. + * @function + * @name lowerCase + * @param {String} str + * @returns {String} returns a lowercase string. ex:hello , o/p: HELLO +*/ + +function upperCase(str) { + return str.toUpperCase() +} module.exports = { camelCaseToTitleCase : camelCaseToTitleCase, lowerCase : lowerCase, @@ -277,5 +289,6 @@ module.exports = { convertProjectStatus : convertProjectStatus, revertProjectStatus:revertProjectStatus, revertStatusorNot:revertStatusorNot, - checkValidUUID : checkValidUUID + checkValidUUID : checkValidUUID, + upperCase : upperCase }; diff --git a/models/projects.js b/models/projects.js index 64d95dc4..738ff6bd 100644 --- a/models/projects.js +++ b/models/projects.js @@ -139,7 +139,10 @@ module.exports = { certificate : { templateId : "ObjectId", osid : String, - transactionId : String, + transactionId : { + type : String, + index : true + }, templateUrl : String, status : String, eligible : Boolean, diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index 81c87ce9..a0282a23 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -25,6 +25,9 @@ module.exports = (req) => { }, share : function () { req.checkParams('_id').exists().withMessage("required project id"); + }, + certificateReIssue : function () { + req.checkParams('_id').exists().withMessage("required project id"); } } From 19c3ac42c24f15da58174a082a0c0505734cb6d8 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 13 Oct 2022 15:58:45 +0530 Subject: [PATCH 172/373] new apis added (pls ignore comments and consoles- not final PR) --- controllers/v1/userProjects.js | 176 +++++++++++++++++ module/userProjects/helper.js | 335 +++++++++++++++++++++++++++++++-- 2 files changed, 499 insertions(+), 12 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index e8019d26..f9c2ece1 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -957,4 +957,180 @@ module.exports = class UserProjects extends Abstract { }) } + /** + * @api {post} /improvement-project/api/v1/userProjects/certificateCallback + * Project certificate callback + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/certificateCallback + * @apiParamExample {json} Request + * { + "event": "sunbird-rc-create", + "timestamp": 1660145509358, + "data": { + "userId": "anonymous", + "entityType": "ProjectCertificate", + "osid": "ce2244a4-1a17-49a0-a3f9-c151161e70bl", + "transactionId": "1-3a4892d8-2221-4e96-9434-f4b37886126b", + "status": "SUCCESSFUL", + "message": "" + }, + "webhookUrl": "http://ml-project-service:3000/v1/userProjects/certificateCallback" + } + * @apiParamExample {json} Response: + /**{ + "message": "Successfully generated project certificate", + "status": 200, + "result": { + "_id": "63446059eeffea2b819f036e" + } + } + /** + + /** + * Project certificate callback. + * @method + * @name certificateCallback + * @param {Object} req - request data. + * @returns {JSON} certificate details. + */ + + async certificateCallback(req) { + return new Promise(async (resolve, reject) => { + try { + let callback = req.body + if ( callback.data && + callback.data.transactionId && + callback.data.transactionId !== "" && + callback.data.osid && + callback.data.osid !== "" + ) { + let certificateDetails = await userProjectsHelper.certificateCallback( callback.data.transactionId, callback.data.osid ); + return resolve({ + message: certificateDetails.message, + result: certificateDetails.data + }); + } + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** + * @api {get} /improvement-project/api/v1/userProjects/certificates + * List of user project with certificate + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/certificates + * @apiParamExample {json} Response: + * { + "message": "User project fetched successfully", + "status": 200, + "result": { + "data": [{ + "_id": "60793b80bd49095a19ddeae1", + "title": "Project with learning resources", + "certificate": { + "osid": "1-21c8ecab-7b8d-40f1-9961-cae7fcb6a5f9", + "status": "active", + "templateId": "600acc42c7de076e6f995147", + "templateUrl": "certificateTemplates/6343bd978f9d8980b7841e85/ba9aa220-ff1b-4717-b6ea-ace55f04fc16_2022-9-10-1665383945769.svg", + "issuedOn": "2020-12-03 13:22:31.988Z" + }, + "status": "submitted" + }, + { + "_id": "6011136a2d25b926974d9ec9", + "title": "Keep Our Schools Alive! (Petition)", + "status": "submitted", + "certificate": { + "eligible": false, + "templateId": "600acc42c7de076e6f995147", + "message": "Not submitted the project the project within program end date" + } + } + ], + "count": 2, + "certificateCount": 1 + } + } + /** + + /** + * List user project details with certificate + * @method + * @name certificates + * @returns {JSON} User project detaills with certificate + */ + + async certificates(req) { + return new Promise(async (resolve, reject) => { + try { + // fetch projects data of user, whish has certificate on completion + let projectDetails = await userProjectsHelper.certificates( req.userDetails.userInformation.userId ); + return resolve({ + message: projectDetails.message, + result: projectDetails.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** + * @api {post} /improvement-project/api/v1/userProjects/certificateReIssue + * ReIssue project certificate (admin api) + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/certificateReIssue + * @apiParamExample {json} Response: + /**{ + "message": "Successfully generated project certificate", + "status": 200, + "result": { + "_id": "63446059eeffea2b819f036e" + } + } + /** + * ReIssue project certificate + * @method + * @name certificateReIssue + * @returns {JSON} Reissued details + */ + + async certificateReIssue(req) { + return new Promise(async (resolve, reject) => { + try { + // ReIssue certificate of given project : projectId is passed as param + let projectDetails = await userProjectsHelper.certificateReIssue( + req.params._id, + req.userDetails.userToken, + req.query.recipientName ? req.query.recipientName : "" + ); + return resolve({ + message: projectDetails.message, + result: projectDetails.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 54c86770..6b400025 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -24,6 +24,7 @@ const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); +const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); /** * UserProjectsHelper @@ -118,7 +119,6 @@ module.exports = class UserProjectsHelper { "appInformation", "status" ]); - if (!userProject.length > 0) { throw { @@ -353,7 +353,7 @@ module.exports = class UserProjectsHelper { if ( data.status == CONSTANTS.common.COMPLETED_STATUS || data.status == CONSTANTS.common.SUBMITTED_STATUS ) { updateProject.completedDate = new Date(); } - + let projectUpdated = await projectQueries.findOneAndUpdate( { @@ -372,9 +372,8 @@ module.exports = class UserProjectsHelper { status: HTTP_STATUS_CODE['bad_request'].status } } - await kafkaProducersHelper.pushProjectToKafka(projectUpdated); - + return resolve({ success: true, message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, @@ -1311,6 +1310,21 @@ module.exports = class UserProjectsHelper { } else { projectDetails.data.status = UTILS.convertProjectStatus(projectDetails.data.status); } + // make templateUrl downloadable befor passing to front-end + if ( projectDetails.data.certificate && + projectDetails.data.certificate.templateUrl && + projectDetails.data.certificate.templateUrl !== "" + ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [projectDetails.data.certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + projectDetails.data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; + } + } return resolve({ success: true, @@ -2279,15 +2293,15 @@ module.exports = class UserProjectsHelper { }) } - /** - * get project details. - * @method - * @name userProject - * @param {String} projectId - project id. - * @returns {Object} Project details. - */ + /** + * get project details. + * @method + * @name userProject + * @param {String} projectId - project id. + * @returns {Object} Project details. + */ - static userProject(projectId) { + static userProject(projectId) { return new Promise(async (resolve, reject) => { try { @@ -2319,6 +2333,303 @@ module.exports = class UserProjectsHelper { }) } + /** + * generate project certificate. + * @method + * @name generateCertificate + * @param {Object} data - certificate creation data. + * @returns {JSON} certificate details. + */ + + static generateCertificate(data) { + return new Promise(async (resolve, reject) => { + try { + // logic to check criteria eligibility to be added + // :Check criteria is sattisfied + // if criteria check passes then call sunbird-RC certificate api + let certificateTemplateDetails = []; + // get downloadable url for certificate template + if ( data.certificate && data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [data.certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; + } else { + return resolve({ + success:false + }); + } + } + if ( data.certificate && data.certificate.templateId && data.certificate.templateId !== "" ) { + certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : data.certificate.templateId + },["issuer","solutionId","programId"]); + + //certificate template data do not exists. + if ( !certificateTemplateDetails.length > 0 ) { + return resolve({ + success:false + }); + } + } + + //create certificate request body + let certificateData = { + recipient : { + id : data.userId, + name : data.userProfile.userName, + type : CONSTANTS.common.PROJECT_CERTIFICATE_RECIPIENT_TYPE + }, + templateUrl : data.certificate.templateUrl, + issuer : certificateTemplateDetails[0].issuer, + status : UTILS.upperCase(data.certificate.status), + projectId : data._id, + projectName : data.title, + programId : certificateTemplateDetails[0].programId, + programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", + solutionId : certificateTemplateDetails[0].solutionId, + solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", + completedDate : data.completedDate + }; + + const certificateDetails = await certificateService.createCertificate( certificateData ); + + let updateObject = { + "$set" : {} + }; + + // if transaction id is present. + if ( certificateDetails.success && + certificateDetails.data && + certificateDetails.data.ProjectCertificate && + certificateDetails.data.ProjectCertificate.transactionId && + certificateDetails.data.ProjectCertificate.transactionId !== "" + ) { + updateObject["$set"]["certificate.transactionId"] = certificateDetails.data.ProjectCertificate.transactionId; + } + + if ( certificateDetails.success && + certificateDetails.data && + certificateDetails.data.ProjectCertificate && + certificateDetails.data.ProjectCertificate.osid && + certificateDetails.data.ProjectCertificate.osid !== "" + ) { + updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; + } + let projectDetails = await projectQueries.findOneAndUpdate( + { + _id: data._id + }, + updateObject + ); + + return resolve( { + success: true + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + + /** + * certificate callback + * @method + * @name certificateCallback + * @param {String} transactionId - transactionId for create certificate. + * @param {String} osid - osid for created certificate. + * @returns {JSON} certificate data updation details. + */ + + static certificateCallback(transactionId, osid) { + return new Promise(async (resolve, reject) => { + try { + let updateObject = { + "$set" : {} + }; + + // update osid and eligibility based on transactionId + updateObject["$set"]["certificate.osid"] = osid; + updateObject["$set"]["certificate.eligible"] = true; + updateObject["$set"]["certificate.message"] = CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED; + updateObject["$set"]["certificate.issuedOn"] = new Date(); + + let projectDetails = await projectQueries.findOneAndUpdate( + { + "certificate.transactionId" : transactionId + }, + updateObject, + { + new: true + } + ); + + if ( projectDetails == null || !Object.keys(projectDetails).length > 0 ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND + } + } + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, + data : { + _id : ObjectId(projectDetails._id) + } + + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + + /** + * List user project details with certificate + * @method + * @name certificates + * @param {String} userId - userId. + * @returns {JSON} certificate data updation details. + */ + + static certificates(userId) { + return new Promise(async (resolve, reject) => { + try { + let certificateCount = 0; + // get project details of user which have certificate. + const userProject = await projectQueries.projectDocument({ + userId: userId, + status: CONSTANTS.common.SUBMITTED_STATUS, + certificate: {$exists:true} + }, [ + "_id", + "title", + "status", + "certificate.osid", + "certificate.transactioId", + "certificate.templateUrl", + "certificate.status", + "certificate.eligible", + "certificate.message", + "certificate.issuedOn" + ]); + + if ( !userProject.length > 0 ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND + } + } + // find certificate generated project count + for ( let projectIndex = 0; projectIndex < userProject.length; projectIndex++ ) { + if ( userProject[projectIndex].certificate && + userProject[projectIndex].certificate.osid && + userProject[projectIndex].certificate.osid !== "" + ) { + certificateCount++; + } + } + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, + data : { + data : userProject, + count : userProject.length, + certificateCount : certificateCount + } + + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + + /** + * Re-Issue project certificate + * @method + * @name certificateReIssue + * @param {String} projectId - projectId. + * @param {String} token - usertoken. + * @param {String} recipientName - recipient name. + * @returns {JSON} certificate re-issued details. + */ + + static certificateReIssue(projectId, token, recipientName = "") { + return new Promise(async (resolve, reject) => { + try { + // get project details project for which certificate re-issue required . + const userProject = await projectQueries.projectDocument({ + _id: projectId + }); + + // if project details not found. + if (!userProject.length > 0) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND + }; + } + + // This logic can be used if we are not going with user read api + if ( recipientName != "" ) { + userProject[0].userProfile.userName = recipientName + } + + // fetch user data using userId of project and calling the profile API + // let userProfileData = await userProfileService.profile(token, userProject[0].userId); + // if ( userProfileData.success && + // userProfileData.data && + // userProfileData.data.response && + // userProfileData.data.response.userName && + // userProfileData.data.response.userName !== "" + // ) { + // userProject[0].userName = userProfileData.data.response.userName; + // } else { + // throw { + // status: HTTP_STATUS_CODE['bad_request'].status, + // message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND + // }; + // } + // await kafkaProducersHelper.pushProjectToKafka(userProject[0]); + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, + data : { + _id : userProject[0]._id + } + + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + + }; /** From f68aafe95d7a014cd25891c14a6b7d7eb125b90c Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 17 Oct 2022 18:43:30 +0530 Subject: [PATCH 173/373] certificate-story --- .env.sample | 5 +- config/kafka.js | 6 +- controllers/v1/userProjects.js | 8 +- envVariables.js | 4 + generics/constants/common.js | 3 +- generics/constants/endpoints.js | 3 +- generics/helpers/utils.js | 102 ++++- ...teSubmissions.js => projectCertificate.js} | 8 +- generics/kafka/consumers/submissions.js | 2 +- generics/services/certificate.js | 65 +++ generics/services/users.js | 51 ++- models/projects.js | 5 +- module/userProjects/helper.js | 429 +++++++++++++----- module/userProjects/validator/v1.js | 5 + 14 files changed, 565 insertions(+), 131 deletions(-) rename generics/kafka/consumers/{certificateSubmissions.js => projectCertificate.js} (81%) create mode 100644 generics/services/certificate.js diff --git a/.env.sample b/.env.sample index f6307ace..f41c8cdd 100644 --- a/.env.sample +++ b/.env.sample @@ -30,4 +30,7 @@ SUBMISSION_TOPIC = "dev.sl.projects.submissions" PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.submissions" // project submission topic # SUNBIRD LOCATION AND USER READ -USER_SERVICE_URL = "http://user-service:3000" // service used for user profile read location search are using this base url \ No newline at end of file +USER_SERVICE_URL = "http://user-service:3000" // service used for user profile read location search are using this base url + +#service name +SERVICE_NAME = ml-project-service // ml-project service name \ No newline at end of file diff --git a/config/kafka.js b/config/kafka.js index 23cdfbc8..3e959a19 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -89,9 +89,9 @@ var _sendToKafkaConsumers = function (topic,host) { if (message && message.topic === SUBMISSION_TOPIC) { submissionsConsumer.messageReceived(message); } - // call certificateSubmissionsConsumer + // call projectCertificateConsumer if (message && message.topic === CERTIFICATE_TOPIC) { - certificateSubmissionsConsumer.messageReceived(message); + projectCertificateConsumer.messageReceived(message); } }); @@ -102,7 +102,7 @@ var _sendToKafkaConsumers = function (topic,host) { submissionsConsumer.errorTriggered(error); } if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { - certificateSubmissionsConsumer.errorTriggered(error); + projectCertificateConsumer.errorTriggered(error); } }); diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index f9c2ece1..663044d0 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -126,7 +126,6 @@ module.exports = class UserProjects extends Abstract { async sync(req) { return new Promise(async (resolve, reject) => { try { - let createdProject = await userProjectsHelper.sync( req.params._id, req.query.lastDownloadedAt, @@ -999,10 +998,7 @@ module.exports = class UserProjects extends Abstract { return new Promise(async (resolve, reject) => { try { let callback = req.body - if ( callback.data && - callback.data.transactionId && - callback.data.transactionId !== "" && - callback.data.osid && + if ( callback.data.transactionId !== "" && callback.data.osid !== "" ) { let certificateDetails = await userProjectsHelper.certificateCallback( callback.data.transactionId, callback.data.osid ); @@ -1115,8 +1111,6 @@ module.exports = class UserProjects extends Abstract { // ReIssue certificate of given project : projectId is passed as param let projectDetails = await userProjectsHelper.certificateReIssue( req.params._id, - req.userDetails.userToken, - req.query.recipientName ? req.query.recipientName : "" ); return resolve({ message: projectDetails.message, diff --git a/envVariables.js b/envVariables.js index 8ce15ac4..31447958 100644 --- a/envVariables.js +++ b/envVariables.js @@ -39,6 +39,10 @@ let enviromentVariables = { "USER_SERVICE_URL" : { "message" : "Required user service base url", "optional" : false + }, + "SERVICE_NAME" : { + "message" : "Required ml-project-service name", + "optional" : false } } diff --git a/generics/constants/common.js b/generics/constants/common.js index ecc4ba61..30e2703c 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -51,6 +51,5 @@ module.exports = { "SERVER_TIME_OUT" : 5000, "OK" : "OK", "PROJECT" : "project", - "PROJECT_CERTIFICATE_RECIPIENT_TYPE" : "user", - "PROJECT_CERTIFICATE_GENERATED" : "Certificate generated successfully" + "PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY" : "Certificate generated successfully" }; diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 5cde94a3..109dfaf2 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -49,5 +49,6 @@ module.exports = { USER_READ_V5 : "/v5/user/read", GET_LOCATION_DATA : "/v1/location/search", CERTIFICATE_CREATE : "/api/v1/ProjectCertificate", - CERTIFICATE_API_CALLBACK : "/api/userProject/mlproject/v1/certificateCallback" + PROJECT_CERTIFICATE_API_CALLBACK : "/v1/userProject/certificateCallback", + USER_READ_PRIVATE : "/private/user/v1/read" // !Caution: End point for reading user details without token. Do not use for public work flow }; diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index b4b1f62c..be149348 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -268,14 +268,107 @@ function checkValidUUID(uuids) { /** * convert string to upperCase. * @function - * @name lowerCase + * @name upperCase * @param {String} str - * @returns {String} returns a lowercase string. ex:hello , o/p: HELLO + * @returns {String} returns a upperCase string. ex:hello , o/p: HELLO */ function upperCase(str) { return str.toUpperCase() } + +/** + * make dates comparable + * @function + * @name createComparableDates + * @param {String} dateArg1 + * @param {String} dateArg2 + * @returns {Object} - date object +*/ + +function createComparableDates(dateArg1, dateArg2) { + let date1 + if(typeof dateArg1 === "string") { + date1 = new Date(dateArg1.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")) + } else { + date1 = new Date(dateArg1) + } + + let date2 + if(typeof dateArg2 === "string") { + date2 = new Date(dateArg2.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")) + } else { + date2 = new Date(dateArg2) + } + + date1.setHours(0) + date1.setMinutes(0) + date1.setSeconds(0) + date2.setHours(0) + date2.setMinutes(0) + date2.setSeconds(0) + return({ + dateOne: date1, + dateTwo: date2 + }) +} + +/** + * count attachments + * @function + * @name getAttachmentCount + * @param {Object} data - data to count + * @param {Object} filter - filter data + * @returns {Number} - attachment count +*/ + +function getAttachmentCount(data, filter) { + if ( !filter || !Object.keys(filter).length > 0 ) { + return 0 + } + if ( !data.length > 0 ) { + return 0; + } else { + if ( filter.value == "all" ){ + return data.length; + } else { + let count = 0; + for ( let attachment = 0; attachment < data.length; attachment++ ) { + if ( data[attachment][filter.key] == filter.value ) { + count++ + } + } + return count; + } + } +} + +/** + * validate lhs and rhs using operator passed as String + * @function + * @name operatorValidation + * @param {Number or String} valueLhs + * @param {Number or String} valueRhs + * @returns {Boolean} - validation result +*/ + +function operatorValidation(valueLhs, valueRhs, operator) { + return new Promise(async (resolve, reject) => { + let result = false; + if (operator == "==" ) { + result = (valueLhs == valueRhs) ? true : false + } else if (operator == "!=" ) { + result = (valueLhs != valueRhs) ? true : false + } else if (operator == ">" ) { + result = (valueLhs > valueRhs) ? true : false + } else if (operator == "<" ) { + result = (valueLhs < valueRhs) ? true : false + } + return resolve(result) + }) +} + + module.exports = { camelCaseToTitleCase : camelCaseToTitleCase, lowerCase : lowerCase, @@ -290,5 +383,8 @@ module.exports = { revertProjectStatus:revertProjectStatus, revertStatusorNot:revertStatusorNot, checkValidUUID : checkValidUUID, - upperCase : upperCase + upperCase : upperCase, + createComparableDates : createComparableDates, + getAttachmentCount : getAttachmentCount, + operatorValidation : operatorValidation }; diff --git a/generics/kafka/consumers/certificateSubmissions.js b/generics/kafka/consumers/projectCertificate.js similarity index 81% rename from generics/kafka/consumers/certificateSubmissions.js rename to generics/kafka/consumers/projectCertificate.js index bca98ab2..d01f0d10 100644 --- a/generics/kafka/consumers/certificateSubmissions.js +++ b/generics/kafka/consumers/projectCertificate.js @@ -1,5 +1,5 @@ /** - * name : certificateSubmissions.js + * name : projectCertificate.js * author : Vishnu * created-date : 10-Oct-2022 * Description : Project certificates submission consumer. @@ -22,10 +22,8 @@ var messageReceived = function (message) { try { // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. - let parsedMessage = JSON.parse(message.value); - if ( parsedMessage.status == CONSTANTS.common.SUBMITTED_STATUS && parsedMessage.certificate ) { - await userProjectsHelper.generateCertificate(parsedMessage); - } + let parsedMessage = JSON.parse( message.value ); + await userProjectsHelper.generateCertificate( parsedMessage ); return resolve("Message Received"); } catch (error) { return reject(error); diff --git a/generics/kafka/consumers/submissions.js b/generics/kafka/consumers/submissions.js index 9c56c4d3..e2411f53 100644 --- a/generics/kafka/consumers/submissions.js +++ b/generics/kafka/consumers/submissions.js @@ -25,7 +25,7 @@ var messageReceived = function (message) { try { let parsedMessage = JSON.parse(message.value); - + let submissionDocument = { "_id" : parsedMessage._id.toString(), "status" : parsedMessage.status, diff --git a/generics/services/certificate.js b/generics/services/certificate.js new file mode 100644 index 00000000..60238069 --- /dev/null +++ b/generics/services/certificate.js @@ -0,0 +1,65 @@ +/** + * name : certificate.js + * author : Vishnu + * Date : 07-Oct-2022 + * Description : Sunbird-RC certificate api. + */ + +//dependencies +const request = require('request'); +const CERTIFICATE_SERVICE_URL = process.env.CERTIFICATE_SERVICE_URL; +const ML_PROJECT_URL = `https://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; + +/** + * Project certificate creation + * @function + * @name createCertificate + * @param {Object} bodyData - Body data + * @returns {JSON} - Certificate creation details. +*/ + +const createCertificate = function (bodyData) { + return new Promise(async (resolve, reject) => { + try { + const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; + let certificateCreateUrl = + CERTIFICATE_SERVICE_URL + + CONSTANTS.endpoints.CERTIFICATE_CREATE + "?mode=async&callback=" + callbackUrl; + + const options = { + headers : { + "content-type": "application/json" + }, + json : bodyData + }; + + request.post(certificateCreateUrl,options,certificateCallback); + + function certificateCallback(err, data) { + + let result = { + success : true + }; + + if (err) { + result.success = false; + } else { + let response = data.body; + if( response.params.status === "SUCCESSFUL" ) { + result["data"] = response.result; + } else { + result.success = false; + } + } + return resolve(result); + } + + } catch (error) { + return reject(error); + } + }) +} + +module.exports = { + createCertificate : createCertificate +} \ No newline at end of file diff --git a/generics/services/users.js b/generics/services/users.js index 53f8edae..57c00fdf 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -176,8 +176,57 @@ async function getParentEntities( entityId, iteration = 0, parentEntities ) { return parentEntities; } + +/** + * get user profileData without token. + * @method + * @name profileReadPrivate + * @param {String} userId - user Id + * @returns {JSON} - User profile details +*/ +const profileReadPrivate = function (userId) { + return new Promise(async (resolve, reject) => { + try { + // <--- Important : This url endpoint is private do not use it for regular workflows ---> + let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_PRIVATE + "/" + userId; + const options = { + headers : { + "content-type": "application/json" + } + }; + request.get(url,options,userReadCallback); + let result = { + success : true + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + + let response = JSON.parse(data.body); + if( response.responseCode === HTTP_STATUS_CODE['ok'].code ) { + result["data"] = response.result; + } else { + result.success = false; + } + + } + return resolve(result); + } + setTimeout(function () { + return resolve (result = { + success : false + }); + }, CONSTANTS.common.SERVER_TIME_OUT); + + } catch (error) { + return reject(error); + } + }) +} module.exports = { profile : profile, locationSearch : locationSearch, - getParentEntities : getParentEntities + getParentEntities : getParentEntities, + profileReadPrivate : profileReadPrivate }; diff --git a/models/projects.js b/models/projects.js index 738ff6bd..0d234bc6 100644 --- a/models/projects.js +++ b/models/projects.js @@ -145,7 +145,10 @@ module.exports = { }, templateUrl : String, status : String, - eligible : Boolean, + eligible : { + type : Boolean, + default : false + }, message : String, issuedOn : Date, criteria : Object diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6b400025..b6780b98 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -104,7 +104,6 @@ module.exports = class UserProjectsHelper { static sync(projectId, lastDownloadedAt, data, userId, userToken, appName = "", appVersion = "") { return new Promise(async (resolve, reject) => { try { - const userProject = await projectQueries.projectDocument({ _id: projectId, userId: userId @@ -353,7 +352,7 @@ module.exports = class UserProjectsHelper { if ( data.status == CONSTANTS.common.COMPLETED_STATUS || data.status == CONSTANTS.common.SUBMITTED_STATUS ) { updateProject.completedDate = new Date(); } - + let projectUpdated = await projectQueries.findOneAndUpdate( { @@ -372,8 +371,15 @@ module.exports = class UserProjectsHelper { status: HTTP_STATUS_CODE['bad_request'].status } } - await kafkaProducersHelper.pushProjectToKafka(projectUpdated); - + + // push to kafka only if project is submitted and certificate key is present + if ( projectUpdated.status == CONSTANTS.common.SUBMITTED_STATUS && + projectUpdated.certificate && + Object.keys(projectUpdated.certificate).length > 0 + ) { + await kafkaProducersHelper.pushProjectToKafka(projectUpdated); + } + return resolve({ success: true, message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, @@ -1170,7 +1176,7 @@ module.exports = class UserProjectsHelper { templateId : certificateTemplateDetails[0]._id, templateUrl : certificateTemplateDetails[0].templateUrl, status : certificateTemplateDetails[0].status, - criteria : certificateTemplateDetails[0].criteria, + criteria : certificateTemplateDetails[0].criteria } } } @@ -2333,104 +2339,163 @@ module.exports = class UserProjectsHelper { }) } + /** + * validate certificate criteria. + * @method + * @name criteriaValidation + * @param {Object} data - project data for certificate creation + * @returns + */ + + static criteriaValidation(data) { + return new Promise(async (resolve, reject) => { + try { + let criteria = data.certificate.criteria; + let validationResult = []; + let validationMessage = ""; + if ( criteria.conditions ) { + let conditions = criteria.conditions; + let conditionKeys = Object.keys(conditions) + + for ( let index = 0; index < conditionKeys.length; index++ ) { + // correntCondition contain the prefinal level data + let currentCondition = conditions[conditionKeys[index]]; + + //now pass expression and validation scope to another function which will start the validation procedure + let validation = await _subCriteriaValidation( currentCondition.conditions, currentCondition.expression, data ); + + validationResult.push(validation.success); + ( validation.success == false ) ? validationMessage = validationMessage + " " + currentCondition.validationText : ""; + } + + return resolve({ + success: criteriaValidation, + message: ( criteriaValidation == false ) ? validationMessage : CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY + }); + } + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + /** * generate project certificate. * @method * @name generateCertificate - * @param {Object} data - certificate creation data. + * @param {Object} data - project data for certificate creation data. * @returns {JSON} certificate details. */ static generateCertificate(data) { return new Promise(async (resolve, reject) => { try { - // logic to check criteria eligibility to be added - // :Check criteria is sattisfied - // if criteria check passes then call sunbird-RC certificate api - let certificateTemplateDetails = []; - // get downloadable url for certificate template - if ( data.certificate && data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: [data.certificate.templateUrl] - } - ); - if ( certificateTemplateDownloadableUrl.success ) { - data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; + // Check criteria is sattisfied if eligible is false + if ( data.certificate.eligible == false ) { + let validateCriteria = await this.criteriaValidation(projectUpdated) + if ( validateCriteria ) { + data.certificate.eligible = true; + data.certificate.message = validateCriteria.message } else { - return resolve({ - success:false - }); + data.certificate.message = validateCriteria.message } } - if ( data.certificate && data.certificate.templateId && data.certificate.templateId !== "" ) { - certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : data.certificate.templateId - },["issuer","solutionId","programId"]); + + // after criteria validation eligibility can change + if ( data.certificate.eligible == false ) { + return resolve( { + success: false + }); + } else { + let certificateTemplateDetails = []; + // get downloadable url for certificate template + if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [data.certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; + } else { + return resolve({ + success:false + }); + } + } + if ( data.certificate.templateId && data.certificate.templateId !== "" ) { + certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : data.certificate.templateId + },["issuer","solutionId","programId"]); - //certificate template data do not exists. - if ( !certificateTemplateDetails.length > 0 ) { + //certificate template data do not exists. + if ( !certificateTemplateDetails.length > 0 ) { + return resolve({ + success:false + }); + } + } + + //create certificate request body + let certificateData = { + recipient : { + id : data.userId, + name : data.userProfile.userName, + type : data.userProfile.userType + }, + templateUrl : data.certificate.templateUrl, + issuer : certificateTemplateDetails[0].issuer, + status : UTILS.upperCase(data.certificate.status), + projectId : data._id, + projectName : data.title, + programId : certificateTemplateDetails[0].programId, + programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", + solutionId : certificateTemplateDetails[0].solutionId, + solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", + completedDate : data.completedDate + }; + + const certificateDetails = await certificateService.createCertificate( certificateData ); + + if ( certificateDetails.success || certificateDetails.data || certificateDetails.data.ProjectCertificate ) { return resolve({ success:false }); } - } - //create certificate request body - let certificateData = { - recipient : { - id : data.userId, - name : data.userProfile.userName, - type : CONSTANTS.common.PROJECT_CERTIFICATE_RECIPIENT_TYPE - }, - templateUrl : data.certificate.templateUrl, - issuer : certificateTemplateDetails[0].issuer, - status : UTILS.upperCase(data.certificate.status), - projectId : data._id, - projectName : data.title, - programId : certificateTemplateDetails[0].programId, - programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", - solutionId : certificateTemplateDetails[0].solutionId, - solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", - completedDate : data.completedDate - }; - - const certificateDetails = await certificateService.createCertificate( certificateData ); - - let updateObject = { - "$set" : {} - }; + let updateObject = { + "$set" : {} + }; - // if transaction id is present. - if ( certificateDetails.success && - certificateDetails.data && - certificateDetails.data.ProjectCertificate && - certificateDetails.data.ProjectCertificate.transactionId && - certificateDetails.data.ProjectCertificate.transactionId !== "" - ) { - updateObject["$set"]["certificate.transactionId"] = certificateDetails.data.ProjectCertificate.transactionId; - } + // if transaction id is present. + if (certificateDetails.data.ProjectCertificate.transactionId && + certificateDetails.data.ProjectCertificate.transactionId !== "" + ) { + updateObject["$set"]["certificate.transactionId"] = certificateDetails.data.ProjectCertificate.transactionId; + } - if ( certificateDetails.success && - certificateDetails.data && - certificateDetails.data.ProjectCertificate && - certificateDetails.data.ProjectCertificate.osid && - certificateDetails.data.ProjectCertificate.osid !== "" - ) { - updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; + if ( certificateDetails.data.ProjectCertificate.osid && + certificateDetails.data.ProjectCertificate.osid !== "" + ) { + updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; + } + let projectDetails = await projectQueries.findOneAndUpdate( + { + _id: data._id + }, + updateObject + ); + + return resolve( { + success: true + }); } - let projectDetails = await projectQueries.findOneAndUpdate( - { - _id: data._id - }, - updateObject - ); - - return resolve( { - success: true - }); - + } catch (error) { return resolve({ success: false, @@ -2460,7 +2525,7 @@ module.exports = class UserProjectsHelper { // update osid and eligibility based on transactionId updateObject["$set"]["certificate.osid"] = osid; updateObject["$set"]["certificate.eligible"] = true; - updateObject["$set"]["certificate.message"] = CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED; + updateObject["$set"]["certificate.message"] = CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY; updateObject["$set"]["certificate.issuedOn"] = new Date(); let projectDetails = await projectQueries.findOneAndUpdate( @@ -2569,17 +2634,17 @@ module.exports = class UserProjectsHelper { * @method * @name certificateReIssue * @param {String} projectId - projectId. - * @param {String} token - usertoken. - * @param {String} recipientName - recipient name. * @returns {JSON} certificate re-issued details. */ - static certificateReIssue(projectId, token, recipientName = "") { + static certificateReIssue(projectId) { return new Promise(async (resolve, reject) => { try { // get project details project for which certificate re-issue required . const userProject = await projectQueries.projectDocument({ - _id: projectId + _id: projectId, + status: CONSTANTS.common.SUBMITTED_STATUS, + certificate: {$exists:true} }); // if project details not found. @@ -2590,27 +2655,22 @@ module.exports = class UserProjectsHelper { }; } - // This logic can be used if we are not going with user read api - if ( recipientName != "" ) { - userProject[0].userProfile.userName = recipientName - } - // fetch user data using userId of project and calling the profile API - // let userProfileData = await userProfileService.profile(token, userProject[0].userId); - // if ( userProfileData.success && - // userProfileData.data && - // userProfileData.data.response && - // userProfileData.data.response.userName && - // userProfileData.data.response.userName !== "" - // ) { - // userProject[0].userName = userProfileData.data.response.userName; - // } else { - // throw { - // status: HTTP_STATUS_CODE['bad_request'].status, - // message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND - // }; - // } - // await kafkaProducersHelper.pushProjectToKafka(userProject[0]); + let userProfileData = await userProfileService.profileReadPrivate(userProject[0].userId); + if ( userProfileData.success && + userProfileData.data && + userProfileData.data.response && + userProfileData.data.response.userName && + userProfileData.data.response.userName !== "" + ) { + userProject[0].userProfile.userName = userProfileData.data.response.userName; + } else { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND + }; + } + await kafkaProducersHelper.pushProjectToKafka(userProject[0]); return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, @@ -2631,6 +2691,163 @@ module.exports = class UserProjectsHelper { }; +/** + * _subCriteriaValidation. + * @method + * @name _subCriteriaValidation + * @param {Object} conditions - condition data. + * @param {String} expression - validation expression + * @returns {Boolean} validation. +*/ + +function _subCriteriaValidation(conditions, expression, data) { + return new Promise(async (resolve, reject) => { + try { + let conditionKeys = Object.keys(conditions) + let validationResult = []; + + for ( let index = 0; index < conditionKeys.length; index++ ) { + let currentCondition = conditions[conditionKeys[index]]; + // correntCondition contain the prefinal level data + //now pass expression and validation scope to another function which will start the validation procedure + let validation = await _validateCriteriaConditions( currentCondition, data ); + validationResult.push(validation); + } + + let subcriteriaValidation = await _criteriaExpressionValidation( expression, conditionKeys, validationResult ) + return resolve({ + success: subcriteriaValidation + }); + + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) + } + }) +} + +/** + * _validateCriteriaConditions. + * @method + * @name _validateCriteriaConditions + * @param {Object} condition - condition data. + * @param {String} data - validation data + * @returns {Boolean} validation. +*/ + +function _validateCriteriaConditions(condition, data) { + return new Promise(async (resolve, reject) => { + try { + let result = false; + if ( !condition.function || condition.function == "" ) { + if( condition.scope == CONSTANTS.common.PROJECT ){ + + // let expression = data[condition.key] + condition.operator + condition.value; + if ( condition.key == "completedDate") { + let comparableDates = UTILS.createComparableDates( data[condition.key], condition.value ); + data[condition.key] = comparableDates.dateOne; + condition.value = comparableDates.dateTwo; + } + result = UTILS.operatorValidation( data[condition.key], condition.value, condition.operator ); + + } + } else { + try { + let valueFromProject = 0; + // if: condition is in scope of project and contains a function to check + if ( condition.scope == CONSTANTS.common.PROJECT ) { + valueFromProject = UTILS.getAttachmentCount( data[condition.key], condition.filter ); + } else if ( condition.scope == CONSTANTS.common.TASK_ATTACHMENT ){ + // for task attachment validatiion _id of specific task or "all" key should be passed in an array called taskDetails + let tasksAttachments = []; + let projectTasks = data.tasks; + + if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 && condition.taskDetails[0] == "all" ) { + + for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { + + if( projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) + { + tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) + } + } + + } else if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 ) { + + // specific task Id or Ids are passed for attachment validation + for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { + for ( let taskDetailsPointer = 0; taskDetailsPointer < condition.taskDetails.length; taskDetailsPointer++ ) { + // get attachments data of specified task/ tasks + if( projectTasks[tasksIndex]._id == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { + tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) + } + } + + } + + } else { + return resolve(result) + } + if ( !tasksAttachments.length > 0 ) { + return resolve(result) + } + valueFromProject = UTILS.getAttachmentCount( tasksAttachments, condition.filter ); + } + result = UTILS.operatorValidation( valueFromProject, condition.value, condition.operator ); + + } catch (fnError) { + return resolve(result) + } + } + return resolve(result); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) + } + }) +} +/** + * _criteriaExpressionValidation + * @method + * @name _criteriaExpressionValidation + * @param {String} expression - criteria expression + * @param {Array} keys - condition keys + * @param {Array} result - condition result + * @returns {Boolean} validation result. +*/ + +function _criteriaExpressionValidation(expression, keys, result) { + return new Promise(async (resolve, reject) => { + try { + + if( expression == "" || + !keys.length > 0 || + !result.length > 0 || + keys.length != result.length ) { + return resolve(false); + } + for ( let pointerToKeys = 0; pointerToKeys < keys.length; pointerToKeys++) { + expression = expression.replace(keys[pointerToKeys],result[pointerToKeys].toString()) + } + let evalResult = eval(expression) + + return resolve(evalResult); + + } catch (error) { + return resolve(false); + } + }) +} /** * Project information. diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index a0282a23..09dcbfa6 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -28,6 +28,11 @@ module.exports = (req) => { }, certificateReIssue : function () { req.checkParams('_id').exists().withMessage("required project id"); + }, + certificateCallback : function () { + req.checkBody("data").exists().withMessage("data is required"); + req.checkBody("data.transactionId").exists().withMessage("transactionId is required"); + req.checkBody("data.osid").exists().withMessage("osid is required"); } } From 9bb3767094f7befc3311f5a974a09154859186a1 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 18 Oct 2022 09:09:07 +0530 Subject: [PATCH 174/373] certificate story --- module/userProjects/helper.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index b6780b98..aa5a6f91 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2396,7 +2396,7 @@ module.exports = class UserProjectsHelper { try { // Check criteria is sattisfied if eligible is false if ( data.certificate.eligible == false ) { - let validateCriteria = await this.criteriaValidation(projectUpdated) + let validateCriteria = await this.criteriaValidation(data) if ( validateCriteria ) { data.certificate.eligible = true; data.certificate.message = validateCriteria.message @@ -2404,7 +2404,6 @@ module.exports = class UserProjectsHelper { data.certificate.message = validateCriteria.message } } - // after criteria validation eligibility can change if ( data.certificate.eligible == false ) { return resolve( { @@ -2461,7 +2460,6 @@ module.exports = class UserProjectsHelper { }; const certificateDetails = await certificateService.createCertificate( certificateData ); - if ( certificateDetails.success || certificateDetails.data || certificateDetails.data.ProjectCertificate ) { return resolve({ success:false From b1de579d9f6d766ef4c36be59aacaa317afc455c Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 20 Oct 2022 18:03:44 +0530 Subject: [PATCH 175/373] certificate story changes --- controllers/v1/userProjects.js | 7 +- envVariables.js | 5 +- generics/constants/api-responses.js | 3 +- .../kafka/consumers/projectCertificate.js | 51 +++-- models/projects.js | 5 +- module/userProjects/helper.js | 188 ++++++++++-------- 6 files changed, 139 insertions(+), 120 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 663044d0..cc904bef 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -997,16 +997,11 @@ module.exports = class UserProjects extends Abstract { async certificateCallback(req) { return new Promise(async (resolve, reject) => { try { - let callback = req.body - if ( callback.data.transactionId !== "" && - callback.data.osid !== "" - ) { - let certificateDetails = await userProjectsHelper.certificateCallback( callback.data.transactionId, callback.data.osid ); + let certificateDetails = await userProjectsHelper.certificateCallback( req.body.data.transactionId, req.body.data.osid ); return resolve({ message: certificateDetails.message, result: certificateDetails.data }); - } } catch (error) { return reject({ status: error.status || HTTP_STATUS_CODE.internal_server_error.status, diff --git a/envVariables.js b/envVariables.js index 31447958..6c5a0974 100644 --- a/envVariables.js +++ b/envVariables.js @@ -41,8 +41,9 @@ let enviromentVariables = { "optional" : false }, "SERVICE_NAME" : { - "message" : "Required ml-project-service name", - "optional" : false + "message" : "Form service base url", + "optional" : true, + "default" : "ml-project-service" } } diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index bd0c1d6a..680092c8 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -126,5 +126,6 @@ module.exports = { "FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED" : "Failed to sync, Project is already Submitted", "SOLUTION_ID_AND_USERPROFILE_REQUIRED": "Required solution Id and userProfile", "PROJECT_WITH_CERTIFICATE_NOT_FOUND": "No certification project found for user", - "PROJECT_CERTIFICATE_GENERATED" : "Successfully generated project certificate" + "PROJECT_CERTIFICATE_GENERATED" : "Successfully generated project certificate", + "TRANSACTION_ID_AND_OSID_REQUIRED" : "Required transactionId and osid" }; diff --git a/generics/kafka/consumers/projectCertificate.js b/generics/kafka/consumers/projectCertificate.js index d01f0d10..1e663057 100644 --- a/generics/kafka/consumers/projectCertificate.js +++ b/generics/kafka/consumers/projectCertificate.js @@ -9,46 +9,43 @@ const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); /** - * submission consumer message received. - * @function - * @name messageReceived - * @param {String} message - consumer data - * @returns {Promise} return a Promise. +* submission consumer message received. +* @function +* @name messageReceived +* @param {String} message - consumer data +* @returns {Promise} return a Promise. */ var messageReceived = function (message) { - return new Promise(async function (resolve, reject) { + try { + // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. + let parsedMessage = JSON.parse( message.value ); + await userProjectsHelper.generateCertificate( parsedMessage ); + return resolve("Message Received"); + } catch (error) { + return reject(error); + } - try { - // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. - let parsedMessage = JSON.parse( message.value ); - await userProjectsHelper.generateCertificate( parsedMessage ); - return resolve("Message Received"); - } catch (error) { - return reject(error); - } - - }); + }); }; /** - * If message is not received. - * @function - * @name errorTriggered - * @param {Object} error - error object - * @returns {Promise} return a Promise. +* If message is not received. +* @function +* @name errorTriggered +* @param {Object} error - error object +* @returns {Promise} return a Promise. */ var errorTriggered = function (error) { - return new Promise(function (resolve, reject) { - try { - return resolve(error); - } catch (error) { - return reject(error); - } + try { + return resolve(error); + } catch (error) { + return reject(error); + } }); }; diff --git a/models/projects.js b/models/projects.js index 0d234bc6..738ff6bd 100644 --- a/models/projects.js +++ b/models/projects.js @@ -145,10 +145,7 @@ module.exports = { }, templateUrl : String, status : String, - eligible : { - type : Boolean, - default : false - }, + eligible : Boolean, message : String, issuedOn : Date, criteria : Object diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index aa5a6f91..4cf0e44b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2353,7 +2353,7 @@ module.exports = class UserProjectsHelper { let criteria = data.certificate.criteria; let validationResult = []; let validationMessage = ""; - if ( criteria.conditions ) { + if ( criteria.conditions && Object.keys(criteria.conditions).length > 0 ) { let conditions = criteria.conditions; let conditionKeys = Object.keys(conditions) @@ -2373,6 +2373,9 @@ module.exports = class UserProjectsHelper { message: ( criteriaValidation == false ) ? validationMessage : CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY }); } + return resolve({ + success: false + }) } catch (error) { return resolve({ success: false, @@ -2394,106 +2397,120 @@ module.exports = class UserProjectsHelper { static generateCertificate(data) { return new Promise(async (resolve, reject) => { try { - // Check criteria is sattisfied if eligible is false - if ( data.certificate.eligible == false ) { + // if eligible key is not there check criteria for validation + if ( !data.certificate.eligible ) { let validateCriteria = await this.criteriaValidation(data) if ( validateCriteria ) { data.certificate.eligible = true; - data.certificate.message = validateCriteria.message } else { + data.certificate.eligible = false; data.certificate.message = validateCriteria.message } } - // after criteria validation eligibility can change - if ( data.certificate.eligible == false ) { + if ( data.certificate.eligible === true && ( data.certificate.transactionId || data.certificate.osid ) ) { return resolve( { success: false }); } else { - let certificateTemplateDetails = []; - // get downloadable url for certificate template - if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: [data.certificate.templateUrl] + if ( data.certificate.eligible === true ) { + let certificateTemplateDetails = []; + // get downloadable url for certificate template + if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [data.certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; + } else { + return resolve({ + success:false + }); } - ); - if ( certificateTemplateDownloadableUrl.success ) { - data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; - } else { + } + if ( data.certificate.templateId && data.certificate.templateId !== "" ) { + certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : data.certificate.templateId + },["issuer","solutionId","programId"]); + + //certificate template data do not exists. + if ( !certificateTemplateDetails.length > 0 ) { + return resolve({ + success:false + }); + } + } + + //create certificate request body + let certificateData = { + recipient : { + id : data.userId, + name : data.userProfile.userName, + type : data.userProfile.userType + }, + templateUrl : data.certificate.templateUrl, + issuer : certificateTemplateDetails[0].issuer, + status : UTILS.upperCase(data.certificate.status), + projectId : data._id, + projectName : data.title, + programId : certificateTemplateDetails[0].programId, + programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", + solutionId : certificateTemplateDetails[0].solutionId, + solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", + completedDate : data.completedDate + }; + + const certificateDetails = await certificateService.createCertificate( certificateData ); + if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { return resolve({ success:false }); } - } - if ( data.certificate.templateId && data.certificate.templateId !== "" ) { - certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : data.certificate.templateId - },["issuer","solutionId","programId"]); + + let updateObject = { + "$set" : {} + }; - //certificate template data do not exists. - if ( !certificateTemplateDetails.length > 0 ) { + // if transaction id is present. + if ( certificateDetails.data.ProjectCertificate.transactionId && + certificateDetails.data.ProjectCertificate.transactionId !== "" + ) { + let transactionIdvalue = certificateDetails.data.ProjectCertificate.transactionId; + transactionIdvalue = transactionIdvalue.split("1-") + updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; + } + + if ( certificateDetails.data.ProjectCertificate.osid && + certificateDetails.data.ProjectCertificate.osid !== "" + ) { + updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; + } + + if ( Object.keys(updateObject["$set"]) > 0 ) { + let projectDetails = await projectQueries.findOneAndUpdate( + { + _id: data._id + }, + updateObject + ); + + return resolve( { + success: true + }); + } else { return resolve({ success:false }); } - } - - //create certificate request body - let certificateData = { - recipient : { - id : data.userId, - name : data.userProfile.userName, - type : data.userProfile.userType - }, - templateUrl : data.certificate.templateUrl, - issuer : certificateTemplateDetails[0].issuer, - status : UTILS.upperCase(data.certificate.status), - projectId : data._id, - projectName : data.title, - programId : certificateTemplateDetails[0].programId, - programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", - solutionId : certificateTemplateDetails[0].solutionId, - solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", - completedDate : data.completedDate - }; - - const certificateDetails = await certificateService.createCertificate( certificateData ); - if ( certificateDetails.success || certificateDetails.data || certificateDetails.data.ProjectCertificate ) { + + } else { return resolve({ success:false }); } - - let updateObject = { - "$set" : {} - }; - - // if transaction id is present. - if (certificateDetails.data.ProjectCertificate.transactionId && - certificateDetails.data.ProjectCertificate.transactionId !== "" - ) { - updateObject["$set"]["certificate.transactionId"] = certificateDetails.data.ProjectCertificate.transactionId; - } - - if ( certificateDetails.data.ProjectCertificate.osid && - certificateDetails.data.ProjectCertificate.osid !== "" - ) { - updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; - } - let projectDetails = await projectQueries.findOneAndUpdate( - { - _id: data._id - }, - updateObject - ); - - return resolve( { - success: true - }); } - } catch (error) { return resolve({ success: false, @@ -2516,13 +2533,18 @@ module.exports = class UserProjectsHelper { static certificateCallback(transactionId, osid) { return new Promise(async (resolve, reject) => { try { + if ( transactionId == "" || osid == "" ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.TRANSACTION_ID_AND_OSID_REQUIRED + } + } let updateObject = { "$set" : {} }; // update osid and eligibility based on transactionId updateObject["$set"]["certificate.osid"] = osid; - updateObject["$set"]["certificate.eligible"] = true; updateObject["$set"]["certificate.message"] = CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY; updateObject["$set"]["certificate.issuedOn"] = new Date(); @@ -2668,6 +2690,12 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND }; } + if ( userProject[0].certificate.transactionId ) { + delete userProject[0].certificate.transactionId; + } + if ( userProject[0].certificate.osid ) { + delete userProject[0].certificate.osid; + } await kafkaProducersHelper.pushProjectToKafka(userProject[0]); return resolve({ success: true, @@ -2743,7 +2771,7 @@ function _validateCriteriaConditions(condition, data) { try { let result = false; if ( !condition.function || condition.function == "" ) { - if( condition.scope == CONSTANTS.common.PROJECT ){ + if ( condition.scope == CONSTANTS.common.PROJECT ){ // let expression = data[condition.key] + condition.operator + condition.value; if ( condition.key == "completedDate") { @@ -2769,7 +2797,7 @@ function _validateCriteriaConditions(condition, data) { for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { - if( projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) + if ( projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) } @@ -2781,7 +2809,7 @@ function _validateCriteriaConditions(condition, data) { for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { for ( let taskDetailsPointer = 0; taskDetailsPointer < condition.taskDetails.length; taskDetailsPointer++ ) { // get attachments data of specified task/ tasks - if( projectTasks[tasksIndex]._id == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { + if ( projectTasks[tasksIndex]._id == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) } } @@ -2834,7 +2862,7 @@ function _criteriaExpressionValidation(expression, keys, result) { keys.length != result.length ) { return resolve(false); } - for ( let pointerToKeys = 0; pointerToKeys < keys.length; pointerToKeys++) { + for ( let pointerToKeys = 0; pointerToKeys < keys.length; pointerToKeys++ ) { expression = expression.replace(keys[pointerToKeys],result[pointerToKeys].toString()) } let evalResult = eval(expression) From 5d9394e42404b12203e82b363dba40913bcc1126 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 20 Oct 2022 20:32:01 +0530 Subject: [PATCH 176/373] certificate story changes --- module/userProjects/helper.js | 37 +++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4cf0e44b..9912e114 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1328,7 +1328,7 @@ module.exports = class UserProjectsHelper { } ); if ( certificateTemplateDownloadableUrl.success ) { - projectDetails.data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; + projectDetails.data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; } } @@ -2353,6 +2353,7 @@ module.exports = class UserProjectsHelper { let criteria = data.certificate.criteria; let validationResult = []; let validationMessage = ""; + let validationExpression = criteria.expression if ( criteria.conditions && Object.keys(criteria.conditions).length > 0 ) { let conditions = criteria.conditions; let conditionKeys = Object.keys(conditions) @@ -2367,7 +2368,7 @@ module.exports = class UserProjectsHelper { validationResult.push(validation.success); ( validation.success == false ) ? validationMessage = validationMessage + " " + currentCondition.validationText : ""; } - + let criteriaValidation = await _criteriaExpressionValidation( validationExpression, conditionKeys, validationResult ) return resolve({ success: criteriaValidation, message: ( criteriaValidation == false ) ? validationMessage : CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY @@ -2400,13 +2401,28 @@ module.exports = class UserProjectsHelper { // if eligible key is not there check criteria for validation if ( !data.certificate.eligible ) { let validateCriteria = await this.criteriaValidation(data) - if ( validateCriteria ) { + if ( validateCriteria.success ) { data.certificate.eligible = true; } else { data.certificate.eligible = false; data.certificate.message = validateCriteria.message } } + let updateObject = { + "$set" : {} + }; + updateObject["$set"]["certificate.eligible"] = data.certificate.eligible; + if ( data.certificate.message && data.certificate.message !=="" ) { + updateObject["$set"]["certificate.message"] = data.certificate.message; + } + if ( Object.keys(updateObject["$set"]).length > 0 ) { + await projectQueries.findOneAndUpdate( + { + _id: data._id + }, + updateObject + ); + } if ( data.certificate.eligible === true && ( data.certificate.transactionId || data.certificate.osid ) ) { return resolve( { success: false @@ -2423,7 +2439,7 @@ module.exports = class UserProjectsHelper { } ); if ( certificateTemplateDownloadableUrl.success ) { - data.certificate.templateUrl = certificateTemplateDownloadableUrl.data.url; + data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; } else { return resolve({ success:false @@ -2453,11 +2469,11 @@ module.exports = class UserProjectsHelper { templateUrl : data.certificate.templateUrl, issuer : certificateTemplateDetails[0].issuer, status : UTILS.upperCase(data.certificate.status), - projectId : data._id, + projectId : (data._id).toString(), projectName : data.title, - programId : certificateTemplateDetails[0].programId, + programId : (certificateTemplateDetails[0].programId).toString(), programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", - solutionId : certificateTemplateDetails[0].solutionId, + solutionId : (certificateTemplateDetails[0].solutionId).toString(), solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", completedDate : data.completedDate }; @@ -2478,7 +2494,8 @@ module.exports = class UserProjectsHelper { certificateDetails.data.ProjectCertificate.transactionId !== "" ) { let transactionIdvalue = certificateDetails.data.ProjectCertificate.transactionId; - transactionIdvalue = transactionIdvalue.split("1-") + transactionIdvalue = transactionIdvalue.split("1-"); + let transactionIdData = transactionIdvalue[1]; updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; } @@ -2487,8 +2504,8 @@ module.exports = class UserProjectsHelper { ) { updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; } - - if ( Object.keys(updateObject["$set"]) > 0 ) { + updateObject["$set"]["certificate.eligible"] = true; + if ( Object.keys(updateObject["$set"]).length > 0 ) { let projectDetails = await projectQueries.findOneAndUpdate( { _id: data._id From dc0ad53334f9bae8eb9289084f1be0b01e55980d Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 21 Oct 2022 03:13:25 +0530 Subject: [PATCH 177/373] certificate story change --- module/userProjects/helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9912e114..04f0a799 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2506,7 +2506,7 @@ module.exports = class UserProjectsHelper { } updateObject["$set"]["certificate.eligible"] = true; if ( Object.keys(updateObject["$set"]).length > 0 ) { - let projectDetails = await projectQueries.findOneAndUpdate( + await projectQueries.findOneAndUpdate( { _id: data._id }, @@ -2648,7 +2648,7 @@ module.exports = class UserProjectsHelper { } return resolve({ success: true, - message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, data : { data : userProject, count : userProject.length, From 7a4ac655f27568a56fcd7e53c05d0ff4af3ec9eb Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 27 Oct 2022 15:07:42 +0530 Subject: [PATCH 178/373] env updated --- .env.sample | 6 +++++- envVariables.js | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index f41c8cdd..2e79dd8d 100644 --- a/.env.sample +++ b/.env.sample @@ -33,4 +33,8 @@ PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.submissions" USER_SERVICE_URL = "http://user-service:3000" // service used for user profile read location search are using this base url #service name -SERVICE_NAME = ml-project-service // ml-project service name \ No newline at end of file +SERVICE_NAME = ml-project-service // ml-project service name + +# sunbird-rc service +CERTIFICATE_SERVICE_URL = http://registry-service:8081 // sunbird-RC registry service URL + diff --git a/envVariables.js b/envVariables.js index 6c5a0974..1caa006b 100644 --- a/envVariables.js +++ b/envVariables.js @@ -44,6 +44,11 @@ let enviromentVariables = { "message" : "Form service base url", "optional" : true, "default" : "ml-project-service" + }, + "CERTIFICATE_SERVICE_URL" : { + "message" : "Form service base url", + "optional" : true, + "default" : "http://registry-service:8081" } } From 559bdaf6135b4dae03c1d0b79c98c19413d0dd05 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 28 Oct 2022 17:42:03 +0530 Subject: [PATCH 179/373] review changes --- envVariables.js | 4 +- generics/helpers/utils.js | 17 +- .../kafka/consumers/projectCertificate.js | 7 +- models/certificateTemplates.js | 3 +- models/projects.js | 9 +- module/certificateValidations/helper.js | 227 +++++++++++++++++ module/userProjects/helper.js | 236 +----------------- 7 files changed, 263 insertions(+), 240 deletions(-) create mode 100644 module/certificateValidations/helper.js diff --git a/envVariables.js b/envVariables.js index 1caa006b..a2da8cfb 100644 --- a/envVariables.js +++ b/envVariables.js @@ -41,12 +41,12 @@ let enviromentVariables = { "optional" : false }, "SERVICE_NAME" : { - "message" : "Form service base url", + "message" : "current service name", "optional" : true, "default" : "ml-project-service" }, "CERTIFICATE_SERVICE_URL" : { - "message" : "Form service base url", + "message" : "certificate service base url", "optional" : true, "default" : "http://registry-service:8081" } diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index be149348..11834c61 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -316,15 +316,15 @@ function createComparableDates(dateArg1, dateArg2) { /** * count attachments * @function - * @name getAttachmentCount + * @name noOfElementsInArray * @param {Object} data - data to count * @param {Object} filter - filter data * @returns {Number} - attachment count */ -function getAttachmentCount(data, filter) { +function noOfElementsInArray(data, filter = {}) { if ( !filter || !Object.keys(filter).length > 0 ) { - return 0 + return data.length; } if ( !data.length > 0 ) { return 0; @@ -344,7 +344,7 @@ function getAttachmentCount(data, filter) { } /** - * validate lhs and rhs using operator passed as String + * validate lhs and rhs using operator passed as String/ Number * @function * @name operatorValidation * @param {Number or String} valueLhs @@ -353,7 +353,7 @@ function getAttachmentCount(data, filter) { */ function operatorValidation(valueLhs, valueRhs, operator) { - return new Promise(async (resolve, reject) => { + return new Promise(async (resolve, reject) => { let result = false; if (operator == "==" ) { result = (valueLhs == valueRhs) ? true : false @@ -363,12 +363,15 @@ function operatorValidation(valueLhs, valueRhs, operator) { result = (valueLhs > valueRhs) ? true : false } else if (operator == "<" ) { result = (valueLhs < valueRhs) ? true : false + } else if (operator == "<=" ) { + result = (valueLhs <= valueRhs) ? true : false + } else if (operator == ">=" ) { + result = (valueLhs >= valueRhs) ? true : false } return resolve(result) }) } - module.exports = { camelCaseToTitleCase : camelCaseToTitleCase, lowerCase : lowerCase, @@ -385,6 +388,6 @@ module.exports = { checkValidUUID : checkValidUUID, upperCase : upperCase, createComparableDates : createComparableDates, - getAttachmentCount : getAttachmentCount, + noOfElementsInArray : noOfElementsInArray, operatorValidation : operatorValidation }; diff --git a/generics/kafka/consumers/projectCertificate.js b/generics/kafka/consumers/projectCertificate.js index 1e663057..69389e77 100644 --- a/generics/kafka/consumers/projectCertificate.js +++ b/generics/kafka/consumers/projectCertificate.js @@ -21,7 +21,12 @@ var messageReceived = function (message) { try { // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. let parsedMessage = JSON.parse( message.value ); - await userProjectsHelper.generateCertificate( parsedMessage ); + if ( parsedMessage.status == CONSTANTS.common.SUBMITTED_STATUS && + parsedMessage.certificate && + Object.keys(parsedMessage.certificate).length > 0 + ) { + await userProjectsHelper.generateCertificate( parsedMessage ); + } return resolve("Message Received"); } catch (error) { return reject(error); diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index 40b55e56..e65899f0 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -9,7 +9,8 @@ module.exports = { }, solutionId: { type : "ObjectId", - index : true + index : true, + unique: true }, programId: "ObjectId", criteria: { diff --git a/models/projects.js b/models/projects.js index 738ff6bd..b9f150d7 100644 --- a/models/projects.js +++ b/models/projects.js @@ -138,10 +138,15 @@ module.exports = { userProfile : Object, certificate : { templateId : "ObjectId", - osid : String, + osid : { + type : String, + index : true, + unique : true + }, transactionId : { type : String, - index : true + index : true, + unique : true }, templateUrl : String, status : String, diff --git a/module/certificateValidations/helper.js b/module/certificateValidations/helper.js new file mode 100644 index 00000000..e550079c --- /dev/null +++ b/module/certificateValidations/helper.js @@ -0,0 +1,227 @@ +/** + * name : helper.js + * author : vishnu + * created-date : 26-Oct-2022 + * Description : certificate validation helper functionality. + */ + +// Dependencies + +/** + * certificateValidationsHelper + * @class +*/ + +module.exports = class certificateValidationsHelper { + + /** + * validate certificate criteria. + * @method + * @name criteriaValidation + * @param {Object} data - project data for certificate creation + * @returns + */ + + static criteriaValidation(data) { + return new Promise(async (resolve, reject) => { + try { + let criteria = data.certificate.criteria; + let validationResult = []; + let validationMessage = ""; + let validationExpression = criteria.expression + if ( criteria.conditions && Object.keys(criteria.conditions).length > 0 ) { + let conditions = criteria.conditions; + let conditionKeys = Object.keys(conditions) + + for ( let index = 0; index < conditionKeys.length; index++ ) { + // correntCondition contain the prefinal level data + let currentCondition = conditions[conditionKeys[index]]; + + //now pass expression and validation scope to another function which will start the validation procedure + let validation = await _subCriteriaValidation( currentCondition.conditions, currentCondition.expression, data ); + + validationResult.push(validation.success); + ( validation.success == false ) ? validationMessage = validationMessage + " " + currentCondition.validationText : ""; + } + let criteriaValidation = await _criteriaExpressionValidation( validationExpression, conditionKeys, validationResult ) + return resolve({ + success: criteriaValidation, + message: ( criteriaValidation == false ) ? validationMessage : CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY + }); + } + return resolve({ + success: false + }) + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } +}; + +/** + * _subCriteriaValidation. + * @method + * @name _subCriteriaValidation + * @param {Object} conditions - condition data. + * @param {String} expression - validation expression + * @returns {Boolean} validation. +*/ + +function _subCriteriaValidation(conditions, expression, data) { + return new Promise(async (resolve, reject) => { + try { + let conditionKeys = Object.keys(conditions) + let validationResult = []; + + for ( let index = 0; index < conditionKeys.length; index++ ) { + let currentCondition = conditions[conditionKeys[index]]; + // correntCondition contain the prefinal level data + //now pass expression and validation scope to another function which will start the validation procedure + let validation = await _validateCriteriaConditions( currentCondition, data ); + validationResult.push(validation); + } + + let subcriteriaValidation = await _criteriaExpressionValidation( expression, conditionKeys, validationResult ) + return resolve({ + success: subcriteriaValidation + }); + + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) + } + }) +} + +/** + * _validateCriteriaConditions. + * @method + * @name _validateCriteriaConditions + * @param {Object} condition - condition data. + * @param {String} data - validation data + * @returns {Boolean} validation. +*/ + +function _validateCriteriaConditions(condition, data) { + return new Promise(async (resolve, reject) => { + try { + let result = false; + if ( !condition.function || condition.function == "" ) { + if ( condition.scope == CONSTANTS.common.PROJECT ){ + + if ( condition.key == "completedDate") { + let comparableDates = UTILS.createComparableDates( data[condition.key], condition.value ); + data[condition.key] = comparableDates.dateOne; + condition.value = comparableDates.dateTwo; + } + result = UTILS.operatorValidation( data[condition.key], condition.value, condition.operator ); + + } + } else { + try { + let valueFromProject = 0; + // if: condition is in scope of project and contains a function to check + if ( condition.scope == CONSTANTS.common.PROJECT ) { + valueFromProject = UTILS.noOfElementsInArray( data[condition.key], condition.filter ); + } else if ( condition.scope == CONSTANTS.common.TASK_ATTACHMENT ){ + // for task attachment validatiion _id of specific task or "all" key should be passed in an array called taskDetails + let tasksAttachments = []; + let projectTasks = data.tasks; + + if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 && condition.taskDetails[0] == "all" ) { + + for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { + + if ( projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) + { + tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) + } + } + + } else if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 ) { + + // specific task Id or Ids are passed for attachment validation + for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { + for ( let taskDetailsPointer = 0; taskDetailsPointer < condition.taskDetails.length; taskDetailsPointer++ ) { + // get attachments data of specified task/ tasks + if ( projectTasks[tasksIndex]._id == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { + tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) + } + } + + } + + } else { + return resolve(result) + } + if ( !tasksAttachments.length > 0 ) { + return resolve(result) + } + valueFromProject = UTILS.noOfElementsInArray( tasksAttachments, condition.filter ); + } + result = UTILS.operatorValidation( valueFromProject, condition.value, condition.operator ); + + } catch (fnError) { + return resolve(result) + } + } + return resolve(result); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) + } + }) +} +/** + * _criteriaExpressionValidation + * @method + * @name _criteriaExpressionValidation + * @param {String} expression - criteria expression + * @param {Array} keys - condition keys + * @param {Array} result - condition result + * @returns {Boolean} validation result. +*/ + +function _criteriaExpressionValidation(expression, keys, result) { + return new Promise(async (resolve, reject) => { + try { + + if( expression == "" || + !keys.length > 0 || + !result.length > 0 || + keys.length != result.length ) { + return resolve(false); + } + for ( let pointerToKeys = 0; pointerToKeys < keys.length; pointerToKeys++ ) { + expression = expression.replace(keys[pointerToKeys],result[pointerToKeys].toString()) + } + let evalResult = eval(expression) + + return resolve(evalResult); + + } catch (error) { + return resolve(false); + } + }) +} + + + + + + diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 04f0a799..27774713 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -25,6 +25,8 @@ const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); +const certificateValidationsHelper = require(MODULES_BASE_PATH + "/certificateValidations/helper"); +const _ = require("lodash"); /** * UserProjectsHelper @@ -371,15 +373,9 @@ module.exports = class UserProjectsHelper { status: HTTP_STATUS_CODE['bad_request'].status } } - - // push to kafka only if project is submitted and certificate key is present - if ( projectUpdated.status == CONSTANTS.common.SUBMITTED_STATUS && - projectUpdated.certificate && - Object.keys(projectUpdated.certificate).length > 0 - ) { - await kafkaProducersHelper.pushProjectToKafka(projectUpdated); - } - + // push project details to kafka + await kafkaProducersHelper.pushProjectToKafka(projectUpdated); + return resolve({ success: true, message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, @@ -1172,12 +1168,7 @@ module.exports = class UserProjectsHelper { // create certificate object and add data if certificate template is present. if ( certificateTemplateDetails.length > 0 ) { - projectCreation.data["certificate"] = { - templateId : certificateTemplateDetails[0]._id, - templateUrl : certificateTemplateDetails[0].templateUrl, - status : certificateTemplateDetails[0].status, - criteria : certificateTemplateDetails[0].criteria - } + projectCreation.data["certificate"] = _.pick(certificateTemplateDetails[0], ['_id', 'templateUrl', 'status', 'criteria']); } } @@ -2223,12 +2214,7 @@ module.exports = class UserProjectsHelper { // create certificate object and add data if certificate template is present. if ( certificateTemplateDetails.length > 0 ) { - libraryProjects.data["certificate"] = { - templateId : certificateTemplateDetails[0]._id, - templateUrl : certificateTemplateDetails[0].templateUrl, - status : certificateTemplateDetails[0].status, - criteria : certificateTemplateDetails[0].criteria, - } + libraryProjects.data["certificate"] = _.pick(certificateTemplateDetails[0], ['_id', 'templateUrl', 'status', 'criteria']); } delete libraryProjects.data.solutionInformation.certificateTemplateId; } @@ -2339,54 +2325,6 @@ module.exports = class UserProjectsHelper { }) } - /** - * validate certificate criteria. - * @method - * @name criteriaValidation - * @param {Object} data - project data for certificate creation - * @returns - */ - - static criteriaValidation(data) { - return new Promise(async (resolve, reject) => { - try { - let criteria = data.certificate.criteria; - let validationResult = []; - let validationMessage = ""; - let validationExpression = criteria.expression - if ( criteria.conditions && Object.keys(criteria.conditions).length > 0 ) { - let conditions = criteria.conditions; - let conditionKeys = Object.keys(conditions) - - for ( let index = 0; index < conditionKeys.length; index++ ) { - // correntCondition contain the prefinal level data - let currentCondition = conditions[conditionKeys[index]]; - - //now pass expression and validation scope to another function which will start the validation procedure - let validation = await _subCriteriaValidation( currentCondition.conditions, currentCondition.expression, data ); - - validationResult.push(validation.success); - ( validation.success == false ) ? validationMessage = validationMessage + " " + currentCondition.validationText : ""; - } - let criteriaValidation = await _criteriaExpressionValidation( validationExpression, conditionKeys, validationResult ) - return resolve({ - success: criteriaValidation, - message: ( criteriaValidation == false ) ? validationMessage : CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY - }); - } - return resolve({ - success: false - }) - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {} - }); - } - }) - } - /** * generate project certificate. * @method @@ -2400,7 +2338,7 @@ module.exports = class UserProjectsHelper { try { // if eligible key is not there check criteria for validation if ( !data.certificate.eligible ) { - let validateCriteria = await this.criteriaValidation(data) + let validateCriteria = await certificateValidationsHelper.criteriaValidation(data) if ( validateCriteria.success ) { data.certificate.eligible = true; } else { @@ -2479,6 +2417,7 @@ module.exports = class UserProjectsHelper { }; const certificateDetails = await certificateService.createCertificate( certificateData ); + if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { return resolve({ success:false @@ -2734,163 +2673,6 @@ module.exports = class UserProjectsHelper { }; -/** - * _subCriteriaValidation. - * @method - * @name _subCriteriaValidation - * @param {Object} conditions - condition data. - * @param {String} expression - validation expression - * @returns {Boolean} validation. -*/ - -function _subCriteriaValidation(conditions, expression, data) { - return new Promise(async (resolve, reject) => { - try { - let conditionKeys = Object.keys(conditions) - let validationResult = []; - - for ( let index = 0; index < conditionKeys.length; index++ ) { - let currentCondition = conditions[conditionKeys[index]]; - // correntCondition contain the prefinal level data - //now pass expression and validation scope to another function which will start the validation procedure - let validation = await _validateCriteriaConditions( currentCondition, data ); - validationResult.push(validation); - } - - let subcriteriaValidation = await _criteriaExpressionValidation( expression, conditionKeys, validationResult ) - return resolve({ - success: subcriteriaValidation - }); - - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }) - } - }) -} - -/** - * _validateCriteriaConditions. - * @method - * @name _validateCriteriaConditions - * @param {Object} condition - condition data. - * @param {String} data - validation data - * @returns {Boolean} validation. -*/ - -function _validateCriteriaConditions(condition, data) { - return new Promise(async (resolve, reject) => { - try { - let result = false; - if ( !condition.function || condition.function == "" ) { - if ( condition.scope == CONSTANTS.common.PROJECT ){ - - // let expression = data[condition.key] + condition.operator + condition.value; - if ( condition.key == "completedDate") { - let comparableDates = UTILS.createComparableDates( data[condition.key], condition.value ); - data[condition.key] = comparableDates.dateOne; - condition.value = comparableDates.dateTwo; - } - result = UTILS.operatorValidation( data[condition.key], condition.value, condition.operator ); - - } - } else { - try { - let valueFromProject = 0; - // if: condition is in scope of project and contains a function to check - if ( condition.scope == CONSTANTS.common.PROJECT ) { - valueFromProject = UTILS.getAttachmentCount( data[condition.key], condition.filter ); - } else if ( condition.scope == CONSTANTS.common.TASK_ATTACHMENT ){ - // for task attachment validatiion _id of specific task or "all" key should be passed in an array called taskDetails - let tasksAttachments = []; - let projectTasks = data.tasks; - - if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 && condition.taskDetails[0] == "all" ) { - - for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { - - if ( projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) - { - tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) - } - } - - } else if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 ) { - - // specific task Id or Ids are passed for attachment validation - for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { - for ( let taskDetailsPointer = 0; taskDetailsPointer < condition.taskDetails.length; taskDetailsPointer++ ) { - // get attachments data of specified task/ tasks - if ( projectTasks[tasksIndex]._id == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { - tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) - } - } - - } - - } else { - return resolve(result) - } - if ( !tasksAttachments.length > 0 ) { - return resolve(result) - } - valueFromProject = UTILS.getAttachmentCount( tasksAttachments, condition.filter ); - } - result = UTILS.operatorValidation( valueFromProject, condition.value, condition.operator ); - - } catch (fnError) { - return resolve(result) - } - } - return resolve(result); - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }) - } - }) -} -/** - * _criteriaExpressionValidation - * @method - * @name _criteriaExpressionValidation - * @param {String} expression - criteria expression - * @param {Array} keys - condition keys - * @param {Array} result - condition result - * @returns {Boolean} validation result. -*/ - -function _criteriaExpressionValidation(expression, keys, result) { - return new Promise(async (resolve, reject) => { - try { - - if( expression == "" || - !keys.length > 0 || - !result.length > 0 || - keys.length != result.length ) { - return resolve(false); - } - for ( let pointerToKeys = 0; pointerToKeys < keys.length; pointerToKeys++ ) { - expression = expression.replace(keys[pointerToKeys],result[pointerToKeys].toString()) - } - let evalResult = eval(expression) - - return resolve(evalResult); - - } catch (error) { - return resolve(false); - } - }) -} /** * Project information. From 2b3c85c776aca28ec8bce3d0f0cb177fe19ba1fc Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 28 Oct 2022 17:52:20 +0530 Subject: [PATCH 180/373] schema change --- models/certificateTemplates.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index e65899f0..a6389ce0 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -9,8 +9,8 @@ module.exports = { }, solutionId: { type : "ObjectId", - index : true, - unique: true + unique: true, + index : true }, programId: "ObjectId", criteria: { From 80226487bbeaf7522d875b313ff55c45b23cc193 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 28 Oct 2022 18:47:36 +0530 Subject: [PATCH 181/373] transactionId 1- removed --- module/userProjects/helper.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 27774713..b7433714 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2433,9 +2433,15 @@ module.exports = class UserProjectsHelper { certificateDetails.data.ProjectCertificate.transactionId !== "" ) { let transactionIdvalue = certificateDetails.data.ProjectCertificate.transactionId; - transactionIdvalue = transactionIdvalue.split("1-"); - let transactionIdData = transactionIdvalue[1]; - updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; + const first2 = transactionIdvalue.slice(0, 2); + + if ( first2 === "1-" ) { + transactionIdvalue = transactionIdvalue.split(/1-(.*)/s) + updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; + } else { + updateObject["$set"]["certificate.transactionId"] = transactionIdvalue; + } + } if ( certificateDetails.data.ProjectCertificate.osid && From fb890b3cc2f4ed0a6233632c9fcf30578d2d90e9 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 31 Oct 2022 09:18:19 +0530 Subject: [PATCH 182/373] schema change --- models/certificateTemplates.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index a6389ce0..22751676 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -2,15 +2,19 @@ module.exports = { name: "certificateTemplates", schema: { templateUrl: String, - issuer: Object, + issuer: { + type : Object, + required : true + }, status: { type : String, - required : true + required : true, + default : "ACTIVE" }, solutionId: { type : "ObjectId", - unique: true, - index : true + index : true, + unique : true }, programId: "ObjectId", criteria: { From eb6909a8bcfc0077f5121c3cc580a2a9141fadd1 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Tue, 15 Nov 2022 20:28:17 +0530 Subject: [PATCH 183/373] Changes to prevent userProfile and userRoleInformation mismatch in projects. --- .../updateUserProfileInProjects.js | 331 ++++++++++++++++++ module/userProjects/helper.js | 199 +++++++++++ 2 files changed, 530 insertions(+) create mode 100644 migrations/userProfileAndRoleMismatchInProjects/updateUserProfileInProjects.js diff --git a/migrations/userProfileAndRoleMismatchInProjects/updateUserProfileInProjects.js b/migrations/userProfileAndRoleMismatchInProjects/updateUserProfileInProjects.js new file mode 100644 index 00000000..6f172436 --- /dev/null +++ b/migrations/userProfileAndRoleMismatchInProjects/updateUserProfileInProjects.js @@ -0,0 +1,331 @@ +/** + * name : updateUserProfileInProjects.js + * author : Priyanka Pradeep + * created-date : 10-Nov-2022 + * Description : Migration script for update userProfile in project + */ + + const path = require("path"); + let rootPath = path.join(__dirname, '../../') + require('dotenv').config({ path: rootPath+'/.env' }) + + let _ = require("lodash"); + let mongoUrl = process.env.MONGODB_URL; + let dbName = mongoUrl.split("/").pop(); + let url = mongoUrl.split(dbName)[0]; + var MongoClient = require('mongodb').MongoClient; + var ObjectId = require('mongodb').ObjectID; + + var fs = require('fs'); + const request = require('request'); + + const userServiceUrl = "http://learner-service:9000"; + const endPoint = "/v1/location/search"; + +(async () => { + + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + + let updatedProjectIds = []; + + //get all projects + let projectDocument = await db.collection('projects').find({ + userRoleInformation: {$exists : true}, + userProfile: {$exists : true}, + }).project({ "_id": 1}).toArray(); + + let chunkOfProjectDocument = _.chunk(projectDocument, 10); + let projectIds; + + for (let pointerToProject = 0; pointerToProject < chunkOfProjectDocument.length; pointerToProject++) { + + projectIds = await chunkOfProjectDocument[pointerToProject].map( + projectDoc => { + return projectDoc._id; + } + ); + + let projectDocuments = await db.collection('projects').find({ + _id: { $in : projectIds } + }).project({ + "_id": 1, + "userRoleInformation" : 1, + "userProfile" : 1 + }).toArray(); + + //loop all projects + for ( let count = 0; count < projectDocuments.length; count++ ) { + + let project = projectDocuments[count]; + let userProfile = project.userProfile; + + + let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles + + if(project.userRoleInformation.role) { // Check if userRoleInformation has role value. + let rolesInUserRoleInformation = project.userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. + + let resetCurrentUserProfileRoles = false; // Flag to reset current userProfile.profileUserTypes i.e. if current role in profile is not at all there in userRoleInformation.roles + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { + + // Loop through current roles in userProfile.profileUserTypes + for (let pointerToCurrentProfileUserTypes = 0; pointerToCurrentProfileUserTypes < userProfile.profileUserTypes.length; pointerToCurrentProfileUserTypes++) { + const currentProfileUserType = userProfile.profileUserTypes[pointerToCurrentProfileUserTypes]; + + if(currentProfileUserType.subType && currentProfileUserType.subType !== null) { // If the role has a subType + + // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!project.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.subType.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } else { // If the role subType is null or is not there + + // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!project.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.type.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } + } + } + if(resetCurrentUserProfileRoles) { // Reset userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + } + + // Loop through each subRole in userRoleInformation + for (let pointerToRolesInUserInformation = 0; pointerToRolesInUserInformation < rolesInUserRoleInformation.length; pointerToRolesInUserInformation++) { + const subRole = rolesInUserRoleInformation[pointerToRolesInUserInformation]; + + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { + if(!_.find(userProfile.profileUserTypes, { 'type': subRole.toLowerCase() }) && !_.find(userProfile.profileUserTypes, { 'subType': subRole.toLowerCase() })) { + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + if(subRole.toUpperCase() === "TEACHER") { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } else { // Make a new entry if userProfile.profileUserTypes is empty or does not exist. + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + if(subRole.toUpperCase() === "TEACHER") { // If subRole is teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } + } + + // Create location only object from userRoleInformation + let userRoleInformationLocationObject = _.omit(project.userRoleInformation, ['role']); + + // All location keys from userRoleInformation + let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); + + let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values + + // Loop through all location keys. + for (let pointerToUserRoleInfromationLocationKeys = 0; pointerToUserRoleInfromationLocationKeys < userRoleInfomrationLocationKeys.length; pointerToUserRoleInfromationLocationKeys++) { + + const locationType = userRoleInfomrationLocationKeys[pointerToUserRoleInfromationLocationKeys]; // e.g. state, district, school + const locationValue = userRoleInformationLocationObject[locationType]; // Location UUID values or school code. + + // Check if userProfile.userLocations exists and is an array of length > 0 + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + + if(locationType === "school") { // If location type school exist check if same is there in userProfile.userLocations + if(!_.find(userProfile.userLocations, { 'type': "school", 'code': locationValue })) { + updateUserProfileLocationInformation = true; // School does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } else { // Check if location type is there in userProfile.userLocations and has same value as userRoleInformation + if(!_.find(userProfile.userLocations, { 'type': locationType, 'id': locationValue })) { + updateUserProfileLocationInformation = true; // Location does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } + } else { + updateUserProfileLocationInformation = true; + break; + } + } + + + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + if(userProfile.userLocations.length != userRoleInfomrationLocationKeys.length) { + updateUserProfileLocationInformation = true; + } + } + + // If userProfile.userLocations has to be updated, get all values and set in userProfile. + if(updateUserProfileLocationInformation) { + + //update userLocations in userProfile + let locationIds = []; + let locationCodes = []; + let userLocations = new Array; + + userRoleInfomrationLocationKeys.forEach( requestedDataKey => { + if (checkIfValidUUID(userRoleInformationLocationObject[requestedDataKey])) { + locationIds.push(userRoleInformationLocationObject[requestedDataKey]); + } else { + locationCodes.push(userRoleInformationLocationObject[requestedDataKey]); + } + }) + + //query for fetch location using id + if ( locationIds.length > 0 ) { + let locationQuery = { + "id" : locationIds + } + + let entityData = await locationSearch(locationQuery); + if ( entityData.success ) { + userLocations = entityData.data; + } + } + + // query for fetch location using code + if ( locationCodes.length > 0 ) { + let codeQuery = { + "code" : locationCodes + } + + let entityData = await locationSearch(codeQuery); + if ( entityData.success ) { + userLocations = userLocations.concat(entityData.data); + } + } + + if ( userLocations.length > 0 ) { + userProfile["userLocations"] = userLocations; + } + } + + + //update projects if userProfile role or location information is incorrect + if ( updateUserProfileRoleInformation || updateUserProfileLocationInformation ) { + + let updateObject = { + "$set" : {} + }; + if(updateUserProfileRoleInformation) { + updateObject["$set"]["userProfile.profileUserTypes"] = userProfile.profileUserTypes; + updateObject["$set"]["userProfile.userRoleMismatchFoundAndUpdated"] = true; + } + if(updateUserProfileLocationInformation) { + updateObject["$set"]["userProfile.userLocations"] = userProfile.userLocations; + updateObject["$set"]["userProfile.userLocationsMismatchFoundAndUpdated"] = true; + } + + await db.collection('projects').findOneAndUpdate({ + "_id" : project._id + },updateObject); + + updatedProjectIds.push(project._id.toString()); + } + + } + + //write updated project ids to file + fs.writeFile( + 'updatedProjectIds.json', + + JSON.stringify(updatedProjectIds), + + function (err) { + if (err) { + console.error('Crap happens'); + } + } + ); + } + + function locationSearch ( filterData ) { + return new Promise(async (resolve, reject) => { + try { + + let bodyData={}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = filterData; + const url = userServiceUrl + endPoint; + const options = { + headers : { + "content-type": "application/json" + }, + json : bodyData + }; + + request.post(url,options,requestCallback); + + let result = { + success : true + }; + + function requestCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = data.body; + if( response.responseCode === "OK" && + response.result && + response.result.response && + response.result.response.length > 0 + ) { + let entityResult = new Array; + response.result.response.map(entityData => { + let entity = _.omit(entityData, ['identifier']); + entityResult.push(entity); + }) + result["data"] = entityResult; + result["count"] = response.result.count; + } else { + result.success = false; + } + } + return resolve(result); + } + + setTimeout(function () { + return resolve (result = { + success : false + }); + }, 5000); + + } catch (error) { + return reject(error); + } + }) + } + + console.log("Updated Project Count : ", updatedProjectIds.length) + console.log("completed") + connection.close(); + } + catch (error) { + console.log(error) + } +})().catch(err => console.error(err)); + +function checkIfValidUUID(value) { + const regexExp = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi; + return regexExp.test(value); +} \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1bc5651f..07018ad4 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1101,6 +1101,7 @@ module.exports = class UserProjectsHelper { } solutionDetails = solutionDetails.data[0]; + } let projectCreation = @@ -1266,6 +1267,18 @@ module.exports = class UserProjectsHelper { } projectCreation.data.userRoleInformation = userRoleInformation; + + //compare & update userProfile with userRoleInformation + if ( projectCreation.data.userProfile && userRoleInformation ) { + let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( + projectCreation.data.userProfile, + userRoleInformation + ); + + if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { + projectCreation.data.userProfile = updatedUserProfile.data; + } + } let project = await projectQueries.createProject(projectCreation.data); @@ -3050,7 +3063,193 @@ function _projectData(data) { }) } +/** + * Validate & Update UserProfile in Projects. + * @method + * @name _updateUserProfileBasedOnUserRoleInfo + * @param {Object} userProfile - userProfile data. + * @param {Object} userRoleInformation - userRoleInformation data. + * @returns {Object} updated UserProfile information. +*/ + +function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) { + return new Promise(async (resolve, reject) => { + try { + + + let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles + + if(userRoleInformation.role) { // Check if userRoleInformation has role value. + let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. + + let resetCurrentUserProfileRoles = false; // Flag to reset current userProfile.profileUserTypes i.e. if current role in profile is not at all there in userRoleInformation.roles + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { + + // Loop through current roles in userProfile.profileUserTypes + for (let pointerToCurrentProfileUserTypes = 0; pointerToCurrentProfileUserTypes < userProfile.profileUserTypes.length; pointerToCurrentProfileUserTypes++) { + const currentProfileUserType = userProfile.profileUserTypes[pointerToCurrentProfileUserTypes]; + + if(currentProfileUserType.subType && currentProfileUserType.subType !== null) { // If the role has a subType + + // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!observation.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.subType.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } else { // If the role subType is null or is not there + + // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!observation.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.type.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } + } + } + if(resetCurrentUserProfileRoles) { // Reset userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + } + + // Loop through each subRole in userRoleInformation + for (let pointerToRolesInUserInformation = 0; pointerToRolesInUserInformation < rolesInUserRoleInformation.length; pointerToRolesInUserInformation++) { + const subRole = rolesInUserRoleInformation[pointerToRolesInUserInformation]; + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { + if(!_.find(userProfile.profileUserTypes, { 'type': subRole.toLowerCase() }) && !_.find(userProfile.profileUserTypes, { 'subType': subRole.toLowerCase() })) { + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + if(subRole.toUpperCase() === "TEACHER") { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } else { // Make a new entry if userProfile.profileUserTypes is empty or does not exist. + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + if(subRole.toUpperCase() === "TEACHER") { // If subRole is teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } + } + + if(updateUserProfileRoleInformation) { // If profileUserTypes in userProfile was wrong and is updated as per userRoleInformation + userProfile.userRoleMismatchFoundAndUpdated = true; + } + + // Create location only object from userRoleInformation + let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); + + // All location keys from userRoleInformation + let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); + + let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values + + // Loop through all location keys. + for (let pointerToUserRoleInfromationLocationKeys = 0; pointerToUserRoleInfromationLocationKeys < userRoleInfomrationLocationKeys.length; pointerToUserRoleInfromationLocationKeys++) { + + const locationType = userRoleInfomrationLocationKeys[pointerToUserRoleInfromationLocationKeys]; // e.g. state, district, school + const locationValue = userRoleInformationLocationObject[locationType]; // Location UUID values or school code. + + // Check if userProfile.userLocations exists and is an array of length > 0 + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + if(locationType === "school") { // If location type school exist check if same is there in userProfile.userLocations + if(!_.find(userProfile.userLocations, { 'type': "school", 'code': locationValue })) { + updateUserProfileLocationInformation = true; // School does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } else { // Check if location type is there in userProfile.userLocations and has same value as userRoleInformation + if(!_.find(userProfile.userLocations, { 'type': locationType, 'id': locationValue })) { + updateUserProfileLocationInformation = true; // Location does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } + } else { + updateUserProfileLocationInformation = true; + break; + } + } + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + if(userProfile.userLocations.length != userRoleInfomrationLocationKeys.length) { + updateUserProfileLocationInformation = true; + } + } + // If userProfile.userLocations has to be updated, get all values and set in userProfile. + if(updateUserProfileLocationInformation) { + //update userLocations in userProfile + let locationIds = []; + let locationCodes = []; + let userLocations = new Array; + + userRoleInfomrationLocationKeys.forEach( requestedDataKey => { + if (UTILS.checkIfValidUUID(userRoleInformationLocationObject[requestedDataKey])) { + locationIds.push(userRoleInformationLocationObject[requestedDataKey]); + } else { + locationCodes.push(userRoleInformationLocationObject[requestedDataKey]); + } + }) + + //query for fetch location using id + if ( locationIds.length > 0 ) { + let locationQuery = { + "id" : locationIds + } + + let entityData = await userProfileService.locationSearch(locationQuery); + if ( entityData.success ) { + userLocations = entityData.data; + } + } + + // query for fetch location using code + if ( locationCodes.length > 0 ) { + let codeQuery = { + "code" : locationCodes + } + + let entityData = await userProfileService.locationSearch(codeQuery); + if ( entityData.success ) { + userLocations = userLocations.concat(entityData.data); + } + } + + if ( userLocations.length > 0 ) { + userProfile["userLocations"] = userLocations; + userProfile.userLocationsMismatchFoundAndUpdated = true; // If userLocations in userProfile was wrong and is updated as per userRoleInformation + } + } + + return resolve({ + success: true, + profileMismatchFound : (updateUserProfileLocationInformation || updateUserProfileRoleInformation) ? true : false, + data: updatedUserProfile + }); + + } catch (error) { + return resolve({ + status: error.status || httpStatusCode.internal_server_error.status, + message: error.message || httpStatusCode.internal_server_error.message, + data : false + }); + } + }) +} \ No newline at end of file From 734b80d3b4ad1cdb80c0d0b37bc00693ae871b13 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Tue, 15 Nov 2022 21:13:45 +0530 Subject: [PATCH 184/373] Variable fix. --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 07018ad4..011ffb65 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3241,7 +3241,7 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) return resolve({ success: true, profileMismatchFound : (updateUserProfileLocationInformation || updateUserProfileRoleInformation) ? true : false, - data: updatedUserProfile + data: userProfile }); } catch (error) { From 3c730b48b81c0162669e35f2eba8a80ecca49c76 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Tue, 15 Nov 2022 21:25:43 +0530 Subject: [PATCH 185/373] Code fix. --- module/userProjects/helper.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 011ffb65..4f7cdf31 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -142,6 +142,9 @@ module.exports = class UserProjectsHelper { const projectsModel = Object.keys(schemas["projects"].schema); + if(data.userRoleInformation) delete data.userRoleInformation; + if(data.userProfile) delete data.userProfile; + let updateProject = {}; let projectData = await _projectData(data); if (projectData && projectData.success == true) { @@ -1269,7 +1272,7 @@ module.exports = class UserProjectsHelper { projectCreation.data.userRoleInformation = userRoleInformation; //compare & update userProfile with userRoleInformation - if ( projectCreation.data.userProfile && userRoleInformation ) { + if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( projectCreation.data.userProfile, userRoleInformation From 7f61f91e6d5df57e3cbbfb1d08d7aea6c8c5b6f2 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 16 Nov 2022 18:00:49 +0530 Subject: [PATCH 186/373] review resolves --- .env.sample | 5 +++ envVariables.js | 22 ++++++++++-- generics/constants/api-responses.js | 7 +++- generics/services/certificate.js | 2 +- models/certificateTemplates.js | 6 +++- module/certificateValidations/helper.js | 22 +++++++----- module/userProjects/helper.js | 47 +++++++++++++------------ 7 files changed, 76 insertions(+), 35 deletions(-) diff --git a/.env.sample b/.env.sample index 2e79dd8d..7ad54dc5 100644 --- a/.env.sample +++ b/.env.sample @@ -38,3 +38,8 @@ SERVICE_NAME = ml-project-service # sunbird-rc service CERTIFICATE_SERVICE_URL = http://registry-service:8081 // sunbird-RC registry service URL +#CERTIFICATE_ISSUER_KID +CERTIFICATE_ISSUER_KID = "1-de2ed8d1-e8d8-40a9-b1ba-7694a16a4c8d" // This issuer Kid is used in sunbird RC end + +PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" // Project certificate enable or disable flag + diff --git a/envVariables.js b/envVariables.js index a2da8cfb..8e520e42 100644 --- a/envVariables.js +++ b/envVariables.js @@ -48,7 +48,25 @@ let enviromentVariables = { "CERTIFICATE_SERVICE_URL" : { "message" : "certificate service base url", "optional" : true, - "default" : "http://registry-service:8081" + "default" : "http://registry-service:8081", + "requiredIf" : { + "key": "PROJECT_CERTIFICATE_ON_OFF", + "operator" : "EQUALS", + "value" : "ON" + } + }, + "PROJECT_CERTIFICATE_ON_OFF" : { + "message" : "Enable/Disable project certification", + "optional" : false + }, + "CERTIFICATE_ISSUER_KID" : { + "message" : "Required certificate issuer kid", + "optional" : true, + "requiredIf" : { + "key": "PROJECT_CERTIFICATE_ON_OFF", + "operator" : "EQUALS", + "value" : "ON" + } } } @@ -62,7 +80,7 @@ module.exports = function() { }; let keyCheckPass = true; - + let validRequiredIfOperators = ["EQUALS","NOT_EQUALS"] if(enviromentVariables[eachEnvironmentVariable].optional === true && enviromentVariables[eachEnvironmentVariable].requiredIf diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 680092c8..d212f216 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -127,5 +127,10 @@ module.exports = { "SOLUTION_ID_AND_USERPROFILE_REQUIRED": "Required solution Id and userProfile", "PROJECT_WITH_CERTIFICATE_NOT_FOUND": "No certification project found for user", "PROJECT_CERTIFICATE_GENERATED" : "Successfully generated project certificate", - "TRANSACTION_ID_AND_OSID_REQUIRED" : "Required transactionId and osid" + "TRANSACTION_ID_AND_OSID_REQUIRED" : "Required transactionId and osid", + "PROJECT_CERTIFICATE_GENERATED_ONCE" : "Certificate generated once", + "DOWNLOADABLE_URL_NOT_FOUND" : "Failed to generate downloadable URL", + "CERTIFICATE_TEMPLATE_NOT_FOUND" : "Certificate template details not found", + "CERTIFICATE_GENERATION_FAILED" : "Certificate generation failed", + "NOT_ELIGIBLE_FOR_CERTIFICATE" : "Project is not eligible for certificate" }; diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 60238069..15ba5970 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -8,7 +8,7 @@ //dependencies const request = require('request'); const CERTIFICATE_SERVICE_URL = process.env.CERTIFICATE_SERVICE_URL; -const ML_PROJECT_URL = `https://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; +const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; /** * Project certificate creation diff --git a/models/certificateTemplates.js b/models/certificateTemplates.js index 22751676..0f5ba2d7 100644 --- a/models/certificateTemplates.js +++ b/models/certificateTemplates.js @@ -16,7 +16,11 @@ module.exports = { index : true, unique : true }, - programId: "ObjectId", + programId: { + type : "ObjectId", + index : true, + required : true + }, criteria: { type : Object, required : true diff --git a/module/certificateValidations/helper.js b/module/certificateValidations/helper.js index e550079c..fc9a7a32 100644 --- a/module/certificateValidations/helper.js +++ b/module/certificateValidations/helper.js @@ -25,7 +25,7 @@ module.exports = class certificateValidationsHelper { static criteriaValidation(data) { return new Promise(async (resolve, reject) => { try { - let criteria = data.certificate.criteria; + let criteria = data.certificate.criteria; // criteria conditions for certificate let validationResult = []; let validationMessage = ""; let validationExpression = criteria.expression @@ -43,6 +43,7 @@ module.exports = class certificateValidationsHelper { validationResult.push(validation.success); ( validation.success == false ) ? validationMessage = validationMessage + " " + currentCondition.validationText : ""; } + // validate criteria using defined expression let criteriaValidation = await _criteriaExpressionValidation( validationExpression, conditionKeys, validationResult ) return resolve({ success: criteriaValidation, @@ -77,7 +78,7 @@ function _subCriteriaValidation(conditions, expression, data) { try { let conditionKeys = Object.keys(conditions) let validationResult = []; - + // loop throug conditions of subcriterias for ( let index = 0; index < conditionKeys.length; index++ ) { let currentCondition = conditions[conditionKeys[index]]; // correntCondition contain the prefinal level data @@ -85,7 +86,7 @@ function _subCriteriaValidation(conditions, expression, data) { let validation = await _validateCriteriaConditions( currentCondition, data ); validationResult.push(validation); } - + // validate expression let subcriteriaValidation = await _criteriaExpressionValidation( expression, conditionKeys, validationResult ) return resolve({ success: subcriteriaValidation @@ -116,14 +117,15 @@ function _validateCriteriaConditions(condition, data) { return new Promise(async (resolve, reject) => { try { let result = false; - if ( !condition.function || condition.function == "" ) { + if ( !condition.function || condition.function == "" ) { if ( condition.scope == CONSTANTS.common.PROJECT ){ - + // if validation is on completedDate if ( condition.key == "completedDate") { let comparableDates = UTILS.createComparableDates( data[condition.key], condition.value ); data[condition.key] = comparableDates.dateOne; condition.value = comparableDates.dateTwo; } + // validate prject value with condition value result = UTILS.operatorValidation( data[condition.key], condition.value, condition.operator ); } @@ -132,16 +134,17 @@ function _validateCriteriaConditions(condition, data) { let valueFromProject = 0; // if: condition is in scope of project and contains a function to check if ( condition.scope == CONSTANTS.common.PROJECT ) { + // get count of attachments at project level valueFromProject = UTILS.noOfElementsInArray( data[condition.key], condition.filter ); } else if ( condition.scope == CONSTANTS.common.TASK_ATTACHMENT ){ // for task attachment validatiion _id of specific task or "all" key should be passed in an array called taskDetails let tasksAttachments = []; let projectTasks = data.tasks; - + // check tasks and taskDetails exists if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 && condition.taskDetails[0] == "all" ) { - + // loop through tasks to get attachments for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { - + if ( projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) @@ -167,8 +170,10 @@ function _validateCriteriaConditions(condition, data) { if ( !tasksAttachments.length > 0 ) { return resolve(result) } + // get task attachments count valueFromProject = UTILS.noOfElementsInArray( tasksAttachments, condition.filter ); } + // validate against condition value result = UTILS.operatorValidation( valueFromProject, condition.value, condition.operator ); } catch (fnError) { @@ -207,6 +212,7 @@ function _criteriaExpressionValidation(expression, keys, result) { keys.length != result.length ) { return resolve(false); } + // generate expression string that can be evaluated for ( let pointerToKeys = 0; pointerToKeys < keys.length; pointerToKeys++ ) { expression = expression.replace(keys[pointerToKeys],result[pointerToKeys].toString()) } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index b7433714..cc9218f7 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2336,8 +2336,10 @@ module.exports = class UserProjectsHelper { static generateCertificate(data) { return new Promise(async (resolve, reject) => { try { + // if eligible key is not there check criteria for validation if ( !data.certificate.eligible ) { + // validate certificate data, checking if it passes all criteria let validateCriteria = await certificateValidationsHelper.criteriaValidation(data) if ( validateCriteria.success ) { data.certificate.eligible = true; @@ -2349,6 +2351,7 @@ module.exports = class UserProjectsHelper { let updateObject = { "$set" : {} }; + // update project certificate data updateObject["$set"]["certificate.eligible"] = data.certificate.eligible; if ( data.certificate.message && data.certificate.message !=="" ) { updateObject["$set"]["certificate.message"] = data.certificate.message; @@ -2362,9 +2365,9 @@ module.exports = class UserProjectsHelper { ); } if ( data.certificate.eligible === true && ( data.certificate.transactionId || data.certificate.osid ) ) { - return resolve( { - success: false - }); + throw { + message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED_ONCE + }; } else { if ( data.certificate.eligible === true ) { let certificateTemplateDetails = []; @@ -2379,9 +2382,9 @@ module.exports = class UserProjectsHelper { if ( certificateTemplateDownloadableUrl.success ) { data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; } else { - return resolve({ - success:false - }); + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; } } if ( data.certificate.templateId && data.certificate.templateId !== "" ) { @@ -2391,12 +2394,12 @@ module.exports = class UserProjectsHelper { //certificate template data do not exists. if ( !certificateTemplateDetails.length > 0 ) { - return resolve({ - success:false - }); + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND + }; } } - + certificateTemplateDetails[0].issuer.kid = process.env.CERTIFICATE_ISSUER_KID; //create certificate request body let certificateData = { recipient : { @@ -2419,9 +2422,9 @@ module.exports = class UserProjectsHelper { const certificateDetails = await certificateService.createCertificate( certificateData ); if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { - return resolve({ - success:false - }); + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED + }; } let updateObject = { @@ -2443,7 +2446,7 @@ module.exports = class UserProjectsHelper { } } - + // update project details certificate details if ( certificateDetails.data.ProjectCertificate.osid && certificateDetails.data.ProjectCertificate.osid !== "" ) { @@ -2462,22 +2465,22 @@ module.exports = class UserProjectsHelper { success: true }); } else { - return resolve({ - success:false - }); + throw { + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_UPDATED + }; } } else { - return resolve({ - success:false - }); + throw { + message: CONSTANTS.apiResponses.NOT_ELIGIBLE_FOR_CERTIFICATE + }; } } } catch (error) { return resolve({ success: false, - message: error.message, - data: {} + message: error.message + }); } }) From 675a61936bba6657a57b8e8728072193390df255 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 16 Nov 2022 18:13:37 +0530 Subject: [PATCH 187/373] PROJECT_CERTIFICATE_ON_OFF default value added --- envVariables.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/envVariables.js b/envVariables.js index 8e520e42..66214318 100644 --- a/envVariables.js +++ b/envVariables.js @@ -57,7 +57,8 @@ let enviromentVariables = { }, "PROJECT_CERTIFICATE_ON_OFF" : { "message" : "Enable/Disable project certification", - "optional" : false + "optional" : false, + "default" : "ON" }, "CERTIFICATE_ISSUER_KID" : { "message" : "Required certificate issuer kid", From 7ac5395cfd1cc7a8633370a2ff7499a5fd940a00 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Thu, 17 Nov 2022 18:58:19 +0530 Subject: [PATCH 188/373] Fatal error fix for hotfix code on 5.0.0 --- module/userProjects/helper.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4f7cdf31..e7da3e37 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3096,14 +3096,14 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) if(currentProfileUserType.subType && currentProfileUserType.subType !== null) { // If the role has a subType // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. - if(!observation.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.subType.toUpperCase())) { + if(!userRoleInformation.role.toUpperCase().includes(currentProfileUserType.subType.toUpperCase())) { resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes break; } } else { // If the role subType is null or is not there // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. - if(!observation.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.type.toUpperCase())) { + if(!userRoleInformation.role.toUpperCase().includes(currentProfileUserType.type.toUpperCase())) { resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes break; } @@ -3204,7 +3204,7 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) let userLocations = new Array; userRoleInfomrationLocationKeys.forEach( requestedDataKey => { - if (UTILS.checkIfValidUUID(userRoleInformationLocationObject[requestedDataKey])) { + if (UTILS.checkValidUUID(userRoleInformationLocationObject[requestedDataKey])) { locationIds.push(userRoleInformationLocationObject[requestedDataKey]); } else { locationCodes.push(userRoleInformationLocationObject[requestedDataKey]); @@ -3249,8 +3249,8 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) } catch (error) { return resolve({ - status: error.status || httpStatusCode.internal_server_error.status, - message: error.message || httpStatusCode.internal_server_error.message, + status: error.status || HTTP_STATUS_CODE['internal_server_error'].status, + message: error.message || HTTP_STATUS_CODE['internal_server_error'].message, data : false }); } From fd1348a7018c3a54966185bf7f998e3c23c6e1e4 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 18 Nov 2022 13:33:10 +0530 Subject: [PATCH 189/373] sunbird internal call for issuer-kid added --- envVariables.js | 9 ----- generics/constants/api-responses.js | 3 +- generics/constants/endpoints.js | 3 +- generics/services/certificate.js | 54 ++++++++++++++++++++++++++++- module/userProjects/helper.js | 9 ++++- 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/envVariables.js b/envVariables.js index 66214318..bafea4e3 100644 --- a/envVariables.js +++ b/envVariables.js @@ -59,15 +59,6 @@ let enviromentVariables = { "message" : "Enable/Disable project certification", "optional" : false, "default" : "ON" - }, - "CERTIFICATE_ISSUER_KID" : { - "message" : "Required certificate issuer kid", - "optional" : true, - "requiredIf" : { - "key": "PROJECT_CERTIFICATE_ON_OFF", - "operator" : "EQUALS", - "value" : "ON" - } } } diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index d212f216..0ce30788 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -132,5 +132,6 @@ module.exports = { "DOWNLOADABLE_URL_NOT_FOUND" : "Failed to generate downloadable URL", "CERTIFICATE_TEMPLATE_NOT_FOUND" : "Certificate template details not found", "CERTIFICATE_GENERATION_FAILED" : "Certificate generation failed", - "NOT_ELIGIBLE_FOR_CERTIFICATE" : "Project is not eligible for certificate" + "NOT_ELIGIBLE_FOR_CERTIFICATE" : "Project is not eligible for certificate", + "ISSUER_KID_NOT_FOUND" : "Failed to fetch certificate issuer kid" }; diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 109dfaf2..14509493 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -50,5 +50,6 @@ module.exports = { GET_LOCATION_DATA : "/v1/location/search", CERTIFICATE_CREATE : "/api/v1/ProjectCertificate", PROJECT_CERTIFICATE_API_CALLBACK : "/v1/userProject/certificateCallback", - USER_READ_PRIVATE : "/private/user/v1/read" // !Caution: End point for reading user details without token. Do not use for public work flow + USER_READ_PRIVATE : "/private/user/v1/read", // !Caution: End point for reading user details without token. Do not use for public work flow + GET_CERTIFICATE_KID : "/api/v1/PublicKey/search" }; diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 15ba5970..4ba22669 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -60,6 +60,58 @@ const createCertificate = function (bodyData) { }) } +/** + * Project certificate issuer-kid + * @function + * @name getCertificateIssuerKid + * @returns {JSON} - Certificate issuer kid details. +*/ + +const getCertificateIssuerKid = function () { + return new Promise(async (resolve, reject) => { + try { + let issuerKidUrl = + CERTIFICATE_SERVICE_URL + CONSTANTS.endpoints.GET_CERTIFICATE_KID; + let bodyData = {"filters": {}}; + + const options = { + headers : { + "Content-Type": "application/json" + }, + json : bodyData + }; + request.post(issuerKidUrl,options,getKidCallback); + + function getKidCallback(err, data) { + let result = { + success : true + }; + + if (err) { + result.success = false; + } else { + let response = data.body; + if( response.length > 0 && response[0].osid && response[0].osid !== "" ) { + result["data"] = response[0].osid; + } else { + result.success = false; + } + } + return resolve(result); + } + setTimeout(function () { + return resolve (result = { + success : false + }); + }, CONSTANTS.common.SERVER_TIME_OUT); + + } catch (error) { + return reject(error); + } + }) +} + module.exports = { - createCertificate : createCertificate + createCertificate : createCertificate, + getCertificateIssuerKid : getCertificateIssuerKid } \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index cc9218f7..77dc6234 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2399,7 +2399,14 @@ module.exports = class UserProjectsHelper { }; } } - certificateTemplateDetails[0].issuer.kid = process.env.CERTIFICATE_ISSUER_KID; + // get certificate issuer kid from sunbird-RC + let kidData = await certificateService.getCertificateIssuerKid(); + if( !kidData.success ) { + throw { + message: CONSTANTS.apiResponses.ISSUER_KID_NOT_FOUND + } + } + certificateTemplateDetails[0].issuer.kid = kidData.data; //create certificate request body let certificateData = { recipient : { From c4c6a42e8592c949233716721ef335e3e520a60f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Sun, 20 Nov 2022 19:34:38 +0530 Subject: [PATCH 190/373] review changes --- .env.sample | 3 - envVariables.js | 19 +- generics/helpers/utils.js | 13 -- models/projects.js | 6 +- module/userProjects/helper.js | 371 ++++++++++++++++++++-------------- 5 files changed, 243 insertions(+), 169 deletions(-) diff --git a/.env.sample b/.env.sample index 7ad54dc5..3692dcec 100644 --- a/.env.sample +++ b/.env.sample @@ -38,8 +38,5 @@ SERVICE_NAME = ml-project-service # sunbird-rc service CERTIFICATE_SERVICE_URL = http://registry-service:8081 // sunbird-RC registry service URL -#CERTIFICATE_ISSUER_KID -CERTIFICATE_ISSUER_KID = "1-de2ed8d1-e8d8-40a9-b1ba-7694a16a4c8d" // This issuer Kid is used in sunbird RC end - PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" // Project certificate enable or disable flag diff --git a/envVariables.js b/envVariables.js index bafea4e3..db946621 100644 --- a/envVariables.js +++ b/envVariables.js @@ -8,6 +8,7 @@ const Log = require("log"); let log = new Log("debug"); let table = require("cli-table"); +const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); let tableData = new table(); @@ -129,16 +130,30 @@ module.exports = function() { tableObj[eachEnvironmentVariable] = `FAILED - ${eachEnvironmentVariable} is required`; } } - tableData.push(tableObj); }) log.info(tableData.toString()); - + getKid(); return { success : success } } +async function getKid(){ + if ( enviromentVariables["PROJECT_CERTIFICATE_ON_OFF"] && + enviromentVariables["PROJECT_CERTIFICATE_ON_OFF"].default && + enviromentVariables["PROJECT_CERTIFICATE_ON_OFF"].default === "ON" + ) { + // get certificate issuer kid from sunbird-RC + let kidData = await certificateService.getCertificateIssuerKid(); + if( !kidData.success ) { + console.log("Server stoped . Failed to set certificate issuer Kid value") + process.exit(); + } + global.CERTIFICATE_ISSUER_KID = kidData.data + } +}; + diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 11834c61..900d00e3 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -265,18 +265,6 @@ function checkValidUUID(uuids) { return validateUUID; } -/** - * convert string to upperCase. - * @function - * @name upperCase - * @param {String} str - * @returns {String} returns a upperCase string. ex:hello , o/p: HELLO -*/ - -function upperCase(str) { - return str.toUpperCase() -} - /** * make dates comparable * @function @@ -386,7 +374,6 @@ module.exports = { revertProjectStatus:revertProjectStatus, revertStatusorNot:revertStatusorNot, checkValidUUID : checkValidUUID, - upperCase : upperCase, createComparableDates : createComparableDates, noOfElementsInArray : noOfElementsInArray, operatorValidation : operatorValidation diff --git a/models/projects.js b/models/projects.js index b9f150d7..483602ec 100644 --- a/models/projects.js +++ b/models/projects.js @@ -153,7 +153,11 @@ module.exports = { eligible : Boolean, message : String, issuedOn : Date, - criteria : Object + criteria : Object, + transactionIdCreatedAt : Date, + reIssuedAt : Date, + prevTransactionId : String, + prevOsid : String } }, compoundIndex: [ diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 77dc6234..6e0c712e 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -106,6 +106,7 @@ module.exports = class UserProjectsHelper { static sync(projectId, lastDownloadedAt, data, userId, userToken, appName = "", appVersion = "") { return new Promise(async (resolve, reject) => { try { + const userProject = await projectQueries.projectDocument({ _id: projectId, userId: userId @@ -2333,29 +2334,199 @@ module.exports = class UserProjectsHelper { * @returns {JSON} certificate details. */ - static generateCertificate(data) { + static generateCertificate(data) { return new Promise(async (resolve, reject) => { try { + + // check eligibility of project for certificate creation + let eligibility = await this.checkCertificateEligibility(data); + if (!eligibility ){ + throw { + message: CONSTANTS.apiResponses.NOT_ELIGIBLE_FOR_CERTIFICATE + }; + } + + // create payload for certificate generation + const certificateData = await this.createCertificatePayload(data); + + // call sunbird-RC to create certificate for project + const certificate = await this.createCertificate(certificateData) - // if eligible key is not there check criteria for validation - if ( !data.certificate.eligible ) { - // validate certificate data, checking if it passes all criteria - let validateCriteria = await certificateValidationsHelper.criteriaValidation(data) - if ( validateCriteria.success ) { - data.certificate.eligible = true; + return resolve(certificate); + + } catch (error) { + return resolve({ + success: false, + message: error.message + + }); + } + }) + } + + /** + * check project eligibility for certificate. + * @method + * @name checkCertificateEligibility + * @param {Object} data - project data for certificate creation data. + * @returns {Boolean} certificate eligibilty status. + */ + + static checkCertificateEligibility(data) { + return new Promise(async (resolve, reject) => { + try { + let eligible = false; + let updateObject = { + "$set" : {} + }; + // validate certificate data, checking if it passes all criteria + let validateCriteria = await certificateValidationsHelper.criteriaValidation(data) + if ( validateCriteria.success ) { + eligible = true; + } else { + updateObject["$set"]["certificate.message"] = validateCriteria.message; + } + updateObject["$set"]["certificate.eligible"] = eligible; + + // update project certificate data + await projectQueries.findOneAndUpdate( + { + _id: data._id + }, + updateObject + ); + + return resolve(eligible); + } catch (error) { + return resolve({ + success: false, + message: error.message + + }); + } + }) + } + + /** + * createCertificatePayload. + * @method + * @name createCertificatePayload + * @param {Object} data - project data for certificate creation data. + * @returns {Object} payload for certificate creation. + */ + + static createCertificatePayload(data) { + return new Promise(async (resolve, reject) => { + try { + + // get downloadable url for certificate template + if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [data.certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; } else { - data.certificate.eligible = false; - data.certificate.message = validateCriteria.message + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; } } + + let certificateTemplateDetails =[]; + if ( data.certificate.templateId && data.certificate.templateId !== "" ) { + certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : data.certificate.templateId + },["issuer","solutionId","programId"]); + + //certificate template data do not exists. + if ( !certificateTemplateDetails.length > 0 ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND + }; + } + } + + //create certificate request body + let certificateData = { + recipient : { + id : data.userId, + name : data.userProfile.userName, + type : data.userProfile.userType + }, + templateUrl : data.certificate.templateUrl, + issuer : CERTIFICATE_ISSUER_KID, + status : data.certificate.status.toUpperCase(), + projectId : (data._id).toString(), + projectName : data.title, + programId : (certificateTemplateDetails[0].programId).toString(), + programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", + solutionId : (certificateTemplateDetails[0].solutionId).toString(), + solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", + completedDate : data.completedDate + }; + return resolve(certificateData); + + } catch (error) { + return resolve({ + success: false, + message: error.message + + }); + } + }) + } + + /** + * call sunbird-RC for certificate creation. + * @method + * @name createCertificate + * @param {Object} certificateData - payload for certificate creation data. + * @returns {Boolean} certificate creation status. + */ + + static createCertificate(certificateData) { + return new Promise(async (resolve, reject) => { + try { + + const certificateDetails = await certificateService.createCertificate( certificateData ); + if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED + }; + } + let updateObject = { "$set" : {} }; - // update project certificate data - updateObject["$set"]["certificate.eligible"] = data.certificate.eligible; - if ( data.certificate.message && data.certificate.message !=="" ) { - updateObject["$set"]["certificate.message"] = data.certificate.message; + + // if transaction id is present. + if ( certificateDetails.data.ProjectCertificate.transactionId && + certificateDetails.data.ProjectCertificate.transactionId !== "" + ) { + let transactionIdvalue = certificateDetails.data.ProjectCertificate.transactionId; + const first2 = transactionIdvalue.slice(0, 2); + + if ( first2 === "1-" ) { + transactionIdvalue = transactionIdvalue.split(/1-(.*)/s) + updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; + } else { + updateObject["$set"]["certificate.transactionId"] = transactionIdvalue; + } + + } + + // update project details certificate details + if ( certificateDetails.data.ProjectCertificate.osid && + certificateDetails.data.ProjectCertificate.osid !== "" + ) { + updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; } + updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date();; + if ( Object.keys(updateObject["$set"]).length > 0 ) { await projectQueries.findOneAndUpdate( { @@ -2364,125 +2535,9 @@ module.exports = class UserProjectsHelper { updateObject ); } - if ( data.certificate.eligible === true && ( data.certificate.transactionId || data.certificate.osid ) ) { - throw { - message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED_ONCE - }; - } else { - if ( data.certificate.eligible === true ) { - let certificateTemplateDetails = []; - // get downloadable url for certificate template - if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: [data.certificate.templateUrl] - } - ); - if ( certificateTemplateDownloadableUrl.success ) { - data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; - } else { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND - }; - } - } - if ( data.certificate.templateId && data.certificate.templateId !== "" ) { - certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : data.certificate.templateId - },["issuer","solutionId","programId"]); - - //certificate template data do not exists. - if ( !certificateTemplateDetails.length > 0 ) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND - }; - } - } - // get certificate issuer kid from sunbird-RC - let kidData = await certificateService.getCertificateIssuerKid(); - if( !kidData.success ) { - throw { - message: CONSTANTS.apiResponses.ISSUER_KID_NOT_FOUND - } - } - certificateTemplateDetails[0].issuer.kid = kidData.data; - //create certificate request body - let certificateData = { - recipient : { - id : data.userId, - name : data.userProfile.userName, - type : data.userProfile.userType - }, - templateUrl : data.certificate.templateUrl, - issuer : certificateTemplateDetails[0].issuer, - status : UTILS.upperCase(data.certificate.status), - projectId : (data._id).toString(), - projectName : data.title, - programId : (certificateTemplateDetails[0].programId).toString(), - programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", - solutionId : (certificateTemplateDetails[0].solutionId).toString(), - solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", - completedDate : data.completedDate - }; - - const certificateDetails = await certificateService.createCertificate( certificateData ); - - if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED - }; - } - - let updateObject = { - "$set" : {} - }; - - // if transaction id is present. - if ( certificateDetails.data.ProjectCertificate.transactionId && - certificateDetails.data.ProjectCertificate.transactionId !== "" - ) { - let transactionIdvalue = certificateDetails.data.ProjectCertificate.transactionId; - const first2 = transactionIdvalue.slice(0, 2); - - if ( first2 === "1-" ) { - transactionIdvalue = transactionIdvalue.split(/1-(.*)/s) - updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; - } else { - updateObject["$set"]["certificate.transactionId"] = transactionIdvalue; - } - - } - // update project details certificate details - if ( certificateDetails.data.ProjectCertificate.osid && - certificateDetails.data.ProjectCertificate.osid !== "" - ) { - updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; - } - updateObject["$set"]["certificate.eligible"] = true; - if ( Object.keys(updateObject["$set"]).length > 0 ) { - await projectQueries.findOneAndUpdate( - { - _id: data._id - }, - updateObject - ); - - return resolve( { - success: true - }); - } else { - throw { - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_UPDATED - }; - } - - } else { - throw { - message: CONSTANTS.apiResponses.NOT_ELIGIBLE_FOR_CERTIFICATE - }; - } - } + return resolve( { + success: true + }); } catch (error) { return resolve({ success: false, @@ -2524,10 +2579,7 @@ module.exports = class UserProjectsHelper { { "certificate.transactionId" : transactionId }, - updateObject, - { - new: true - } + updateObject ); if ( projectDetails == null || !Object.keys(projectDetails).length > 0 ) { @@ -2567,7 +2619,7 @@ module.exports = class UserProjectsHelper { static certificates(userId) { return new Promise(async (resolve, reject) => { try { - let certificateCount = 0; + // get project details of user which have certificate. const userProject = await projectQueries.projectDocument({ userId: userId, @@ -2592,22 +2644,18 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND } } - // find certificate generated project count - for ( let projectIndex = 0; projectIndex < userProject.length; projectIndex++ ) { - if ( userProject[projectIndex].certificate && - userProject[projectIndex].certificate.osid && - userProject[projectIndex].certificate.osid !== "" - ) { - certificateCount++; - } - } + + let count = _.countBy(userProject, (rec) => { + return (rec.certificate && rec.certificate.osid && rec.certificate.osid !== "" )? 'generated': 'notGenerated'; + }); + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECTS_FETCHED, data : { data : userProject, count : userProject.length, - certificateCount : certificateCount + certificateCount : count.generated } }); @@ -2646,6 +2694,9 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND }; } + let updateObject = { + "$set" : {} + }; // fetch user data using userId of project and calling the profile API let userProfileData = await userProfileService.profileReadPrivate(userProject[0].userId); @@ -2662,13 +2713,33 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND }; } + + // create payload for certificate generation + const certificateData = await this.createCertificatePayload(userProject[0]); + + // call sunbird-RC to create certificate for project + const certificate = await this.createCertificate(certificateData); + + if ( !certificate.success ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED + }; + } + if ( userProject[0].certificate.transactionId ) { - delete userProject[0].certificate.transactionId; + updateObject["$set"]["certificate.prevTransactionId"] = userProject[0].certificate.transactionId } if ( userProject[0].certificate.osid ) { - delete userProject[0].certificate.osid; + updateObject["$set"]["certificate.prevOsid"] = userProject[0].certificate.osid; } - await kafkaProducersHelper.pushProjectToKafka(userProject[0]); + updateObject["$set"]["certificate.reIssuedAt"] = new Date(); + await projectQueries.findOneAndUpdate( + { + _id: userProject[0]._id + }, + updateObject + ); + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, From 0626929bfdd8a60dc0c7b18810b49bf234947cb5 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Sun, 20 Nov 2022 19:44:17 +0530 Subject: [PATCH 191/373] review changes --- models/projects.js | 11 +++++++---- module/userProjects/helper.js | 8 ++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/models/projects.js b/models/projects.js index 483602ec..254da8d4 100644 --- a/models/projects.js +++ b/models/projects.js @@ -154,10 +154,13 @@ module.exports = { message : String, issuedOn : Date, criteria : Object, - transactionIdCreatedAt : Date, - reIssuedAt : Date, - prevTransactionId : String, - prevOsid : String + originalTransactionInformation :{ + transactionIdCreatedAt : Date, + reIssuedAt : Date, + prevTransactionId : String, + prevOsid : String + } + } }, compoundIndex: [ diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6e0c712e..cb831e7c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2525,7 +2525,7 @@ module.exports = class UserProjectsHelper { ) { updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; } - updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date();; + updateObject["$set"]["certificate.originalTransactionInformation.transactionIdCreatedAt"] = new Date();; if ( Object.keys(updateObject["$set"]).length > 0 ) { await projectQueries.findOneAndUpdate( @@ -2727,12 +2727,12 @@ module.exports = class UserProjectsHelper { } if ( userProject[0].certificate.transactionId ) { - updateObject["$set"]["certificate.prevTransactionId"] = userProject[0].certificate.transactionId + updateObject["$set"]["certificate.originalTransactionInformation.prevTransactionId"] = userProject[0].certificate.transactionId } if ( userProject[0].certificate.osid ) { - updateObject["$set"]["certificate.prevOsid"] = userProject[0].certificate.osid; + updateObject["$set"]["certificate.originalTransactionInformation.prevOsid"] = userProject[0].certificate.osid; } - updateObject["$set"]["certificate.reIssuedAt"] = new Date(); + updateObject["$set"]["certificate.originalTransactionInformation.reIssuedAt"] = new Date(); await projectQueries.findOneAndUpdate( { _id: userProject[0]._id From 56da30fe36c8a9efe3beae40f965038a3e8973ad Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 21 Nov 2022 10:53:33 +0530 Subject: [PATCH 192/373] project model changes --- models/projects.js | 8 ++++---- module/userProjects/helper.js | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/models/projects.js b/models/projects.js index 254da8d4..bdf827c7 100644 --- a/models/projects.js +++ b/models/projects.js @@ -154,11 +154,11 @@ module.exports = { message : String, issuedOn : Date, criteria : Object, + reIssuedAt : Date, + transactionIdCreatedAt : Date, originalTransactionInformation :{ - transactionIdCreatedAt : Date, - reIssuedAt : Date, - prevTransactionId : String, - prevOsid : String + transactionId : String, + osid : String } } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index cb831e7c..6e8e8d4f 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2525,7 +2525,7 @@ module.exports = class UserProjectsHelper { ) { updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; } - updateObject["$set"]["certificate.originalTransactionInformation.transactionIdCreatedAt"] = new Date();; + updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date();; if ( Object.keys(updateObject["$set"]).length > 0 ) { await projectQueries.findOneAndUpdate( @@ -2560,6 +2560,7 @@ module.exports = class UserProjectsHelper { static certificateCallback(transactionId, osid) { return new Promise(async (resolve, reject) => { try { + // callback request structure nested so validating transactionId and osid here instead in validator. if ( transactionId == "" || osid == "" ) { throw { status: HTTP_STATUS_CODE["bad_request"].status, @@ -2727,12 +2728,12 @@ module.exports = class UserProjectsHelper { } if ( userProject[0].certificate.transactionId ) { - updateObject["$set"]["certificate.originalTransactionInformation.prevTransactionId"] = userProject[0].certificate.transactionId + updateObject["$set"]["certificate.originalTransactionInformation.transactionId"] = userProject[0].certificate.transactionId } if ( userProject[0].certificate.osid ) { - updateObject["$set"]["certificate.originalTransactionInformation.prevOsid"] = userProject[0].certificate.osid; + updateObject["$set"]["certificate.originalTransactionInformation.osid"] = userProject[0].certificate.osid; } - updateObject["$set"]["certificate.originalTransactionInformation.reIssuedAt"] = new Date(); + updateObject["$set"]["certificate.reIssuedAt"] = new Date(); await projectQueries.findOneAndUpdate( { _id: userProject[0]._id From 261d78000362b5abed39bbaf24546ace34ff60c4 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 21 Nov 2022 18:12:14 +0530 Subject: [PATCH 193/373] envVariable fix --- envVariables.js | 2 ++ generics/services/certificate.js | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/envVariables.js b/envVariables.js index db946621..13ef9826 100644 --- a/envVariables.js +++ b/envVariables.js @@ -120,6 +120,8 @@ module.exports = function() { && enviromentVariables[eachEnvironmentVariable].default && enviromentVariables[eachEnvironmentVariable].default != "") { process.env[eachEnvironmentVariable] = enviromentVariables[eachEnvironmentVariable].default; + success = true; + keyCheckPass = true; } if(!keyCheckPass) { diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 4ba22669..d0c510ef 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -7,8 +7,6 @@ //dependencies const request = require('request'); -const CERTIFICATE_SERVICE_URL = process.env.CERTIFICATE_SERVICE_URL; -const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; /** * Project certificate creation @@ -21,11 +19,11 @@ const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICA const createCertificate = function (bodyData) { return new Promise(async (resolve, reject) => { try { + const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; let certificateCreateUrl = - CERTIFICATE_SERVICE_URL + + process.env.CERTIFICATE_SERVICE_URL + CONSTANTS.endpoints.CERTIFICATE_CREATE + "?mode=async&callback=" + callbackUrl; - const options = { headers : { "content-type": "application/json" @@ -71,7 +69,7 @@ const getCertificateIssuerKid = function () { return new Promise(async (resolve, reject) => { try { let issuerKidUrl = - CERTIFICATE_SERVICE_URL + CONSTANTS.endpoints.GET_CERTIFICATE_KID; + process.env.CERTIFICATE_SERVICE_URL + CONSTANTS.endpoints.GET_CERTIFICATE_KID; let bodyData = {"filters": {}}; const options = { @@ -81,7 +79,6 @@ const getCertificateIssuerKid = function () { json : bodyData }; request.post(issuerKidUrl,options,getKidCallback); - function getKidCallback(err, data) { let result = { success : true From e6e9ac916af72b2cb019e3c480449fda7b2cbc99 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 23 Nov 2022 14:38:46 +0530 Subject: [PATCH 194/373] added certificate key to projection --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 26c6280c..6d3ecbcf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1941,7 +1941,8 @@ module.exports = class UserProjectsHelper { "lastDownloadedAt", "hasAcceptedTAndC", "referenceFrom", - "status" + "status", + "certificate" ] ); From a08fca099f513084bd86c9419592485c49152090 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 24 Nov 2022 19:31:59 +0530 Subject: [PATCH 195/373] ED-103 staging-fix --- module/userProjects/helper.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6d3ecbcf..360690cd 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1174,7 +1174,8 @@ module.exports = class UserProjectsHelper { // create certificate object and add data if certificate template is present. if ( certificateTemplateDetails.length > 0 ) { - projectCreation.data["certificate"] = _.pick(certificateTemplateDetails[0], ['_id', 'templateUrl', 'status', 'criteria']); + projectCreation.data["certificate"] = _.pick(certificateTemplateDetails[0], ['templateUrl', 'status', 'criteria']); + projectCreation.data["certificate"]["templateId"] = solutionDetails.certificateTemplateId; } } @@ -2225,20 +2226,20 @@ module.exports = class UserProjectsHelper { } // <- Add certificate template data if ( - libraryProjects.data.solutionInformation && - libraryProjects.data.solutionInformation.certificateTemplateId && - libraryProjects.data.solutionInformation.certificateTemplateId !== "" + libraryProjects.data.certificateTemplateId && + libraryProjects.data.certificateTemplateId !== "" ){ // <- Add certificate template details to projectCreation data if present -> const certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : libraryProjects.data.solutionInformation.certificateTemplateId + _id : libraryProjects.data.certificateTemplateId }); // create certificate object and add data if certificate template is present. if ( certificateTemplateDetails.length > 0 ) { - libraryProjects.data["certificate"] = _.pick(certificateTemplateDetails[0], ['_id', 'templateUrl', 'status', 'criteria']); + libraryProjects.data["certificate"] = _.pick(certificateTemplateDetails[0], ['templateUrl', 'status', 'criteria']); } - delete libraryProjects.data.solutionInformation.certificateTemplateId; + libraryProjects.data["certificate"]["templateId"] = libraryProjects.data.certificateTemplateId; + delete libraryProjects.data.certificateTemplateId; } //Fetch user profile information by calling sunbird's user read api. From 3dfb1a33bdc9c1d7419e80b8f0204419fbb88d04 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 24 Nov 2022 22:11:01 +0530 Subject: [PATCH 196/373] model change --- models/project-templates.js | 3 ++- models/solutions.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/models/project-templates.js b/models/project-templates.js index 4fddac32..e1df6b92 100644 --- a/models/project-templates.js +++ b/models/project-templates.js @@ -112,6 +112,7 @@ module.exports = { 4 : 0, 5 : 0 } - } + }, + certificateTemplateId : "ObjectId" } }; \ No newline at end of file diff --git a/models/solutions.js b/models/solutions.js index c55a0508..dacb3a09 100644 --- a/models/solutions.js +++ b/models/solutions.js @@ -96,6 +96,7 @@ module.exports = { type: Number, default: 1 }, - reportInformation : Object + reportInformation : Object, + certificateTemplateId : "ObjectId" } }; \ No newline at end of file From ac074b89ddf2fdf5f9b4b3c5646f4e83dcb1a7fa Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 24 Nov 2022 23:31:09 +0530 Subject: [PATCH 197/373] staging fix --- module/userProjects/helper.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 360690cd..e81723fe 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2112,7 +2112,7 @@ module.exports = class UserProjectsHelper { "", isATargetedSolution ); - + if ( libraryProjects.data && !Object.keys(libraryProjects.data).length > 0 @@ -2372,7 +2372,7 @@ module.exports = class UserProjectsHelper { const certificateData = await this.createCertificatePayload(data); // call sunbird-RC to create certificate for project - const certificate = await this.createCertificate(certificateData) + const certificate = await this.createCertificate(certificateData, data._id) return resolve(certificate); @@ -2470,6 +2470,7 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND }; } + certificateTemplateDetails[0].issuer.kid = CERTIFICATE_ISSUER_KID; } //create certificate request body @@ -2480,7 +2481,7 @@ module.exports = class UserProjectsHelper { type : data.userProfile.userType }, templateUrl : data.certificate.templateUrl, - issuer : CERTIFICATE_ISSUER_KID, + issuer : certificateTemplateDetails[0].issuer, status : data.certificate.status.toUpperCase(), projectId : (data._id).toString(), projectName : data.title, @@ -2507,10 +2508,11 @@ module.exports = class UserProjectsHelper { * @method * @name createCertificate * @param {Object} certificateData - payload for certificate creation data. + * @param {string} projectId - project Id. * @returns {Boolean} certificate creation status. */ - static createCertificate(certificateData) { + static createCertificate(certificateData, projectId) { return new Promise(async (resolve, reject) => { try { @@ -2520,7 +2522,7 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED }; } - + let updateObject = { "$set" : {} }; @@ -2552,7 +2554,7 @@ module.exports = class UserProjectsHelper { if ( Object.keys(updateObject["$set"]).length > 0 ) { await projectQueries.findOneAndUpdate( { - _id: data._id + _id: projectId }, updateObject ); @@ -2741,7 +2743,7 @@ module.exports = class UserProjectsHelper { const certificateData = await this.createCertificatePayload(userProject[0]); // call sunbird-RC to create certificate for project - const certificate = await this.createCertificate(certificateData); + const certificate = await this.createCertificate(certificateData, userProject[0]._id); if ( !certificate.success ) { throw { From 929d9f129a78679609eb4900f6f37ae12029c2b7 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 25 Nov 2022 10:49:03 +0530 Subject: [PATCH 198/373] avoid template url from updation --- module/userProjects/helper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index e81723fe..dc83f2fa 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -147,7 +147,9 @@ module.exports = class UserProjectsHelper { if(data.userRoleInformation) delete data.userRoleInformation; if(data.userProfile) delete data.userProfile; - + // if certificate is there. only templateUrl is removed from certificate object(). + if( data.certificate.templateUrl) delete data.certificate.templateUrl; + let updateProject = {}; let projectData = await _projectData(data); if (projectData && projectData.success == true) { From f2ddb14e8438a6ef5b92afa38d1da98de01a6cba Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 25 Nov 2022 11:00:47 +0530 Subject: [PATCH 199/373] remove certificate key from updation --- module/userProjects/helper.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index dc83f2fa..f4dee69a 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -144,11 +144,11 @@ module.exports = class UserProjectsHelper { } const projectsModel = Object.keys(schemas["projects"].schema); - - if(data.userRoleInformation) delete data.userRoleInformation; - if(data.userProfile) delete data.userProfile; - // if certificate is there. only templateUrl is removed from certificate object(). - if( data.certificate.templateUrl) delete data.certificate.templateUrl; + + let keysToRemoveFromUpdation = ["userRoleInformation","userProfile","certificate"] + keysToRemoveFromUpdation.forEach( key => { + if (data[key])delete data[key]; + }) let updateProject = {}; let projectData = await _projectData(data); From d99d402d0eca21be7f623c2112f5ad799ada3052 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 25 Nov 2022 14:53:37 +0530 Subject: [PATCH 200/373] console added to check in staging --- generics/services/certificate.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/generics/services/certificate.js b/generics/services/certificate.js index d0c510ef..7743ef31 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -19,6 +19,7 @@ const request = require('request'); const createCertificate = function (bodyData) { return new Promise(async (resolve, reject) => { try { + console.log("line 22 payload to RC : ",bodyData) const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; let certificateCreateUrl = @@ -32,13 +33,14 @@ const createCertificate = function (bodyData) { }; request.post(certificateCreateUrl,options,certificateCallback); - + console.log("line 35 certificateCreateUrl :", certificateCreateUrl) function certificateCallback(err, data) { let result = { success : true }; - + console.log("line 41 data from RC call :",data); + console.log("line 41 error from RC call :",err); if (err) { result.success = false; } else { From cf6faaf562fe7ac8dda65e3e81898bd8fcd6b540 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 25 Nov 2022 17:20:21 +0530 Subject: [PATCH 201/373] console added and template details changes --- generics/services/certificate.js | 23 +++++++++++++++-------- module/project/templates/helper.js | 15 ++++++++++++++- module/userProjects/helper.js | 4 ++-- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 7743ef31..b11d7b07 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -19,7 +19,7 @@ const request = require('request'); const createCertificate = function (bodyData) { return new Promise(async (resolve, reject) => { try { - console.log("line 22 payload to RC : ",bodyData) + const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; let certificateCreateUrl = @@ -31,20 +31,21 @@ const createCertificate = function (bodyData) { }, json : bodyData }; - + console.log("requestUrlcertificate create : ",certificateCreateUrl) + console.log("certificateRequestBody : ",bodyData) request.post(certificateCreateUrl,options,certificateCallback); - console.log("line 35 certificateCreateUrl :", certificateCreateUrl) + function certificateCallback(err, data) { let result = { success : true }; - console.log("line 41 data from RC call :",data); - console.log("line 41 error from RC call :",err); + console.log("line 41 error from RC call error :",err.message); if (err) { result.success = false; } else { let response = data.body; + console.log("certificate success response: ",response) if( response.params.status === "SUCCESSFUL" ) { result["data"] = response.result; } else { @@ -55,6 +56,7 @@ const createCertificate = function (bodyData) { } } catch (error) { + console.log("line 58 catch block : ",error.message) return reject(error); } }) @@ -72,24 +74,28 @@ const getCertificateIssuerKid = function () { try { let issuerKidUrl = process.env.CERTIFICATE_SERVICE_URL + CONSTANTS.endpoints.GET_CERTIFICATE_KID; + let bodyData = {"filters": {}}; - + const options = { headers : { "Content-Type": "application/json" }, json : bodyData - }; + }; + console.log("issuer Kid url : ",issuerKidUrl); + console.log("issuer Kid bodyData : ",bodyData); request.post(issuerKidUrl,options,getKidCallback); function getKidCallback(err, data) { let result = { success : true }; - + console.log("KID rc call error : ",err.message) if (err) { result.success = false; } else { let response = data.body; + console.log("KID success response : ",response) if( response.length > 0 && response[0].osid && response[0].osid !== "" ) { result["data"] = response[0].osid; } else { @@ -105,6 +111,7 @@ const getCertificateIssuerKid = function () { }, CONSTANTS.common.SERVER_TIME_OUT); } catch (error) { + console.log("catch error : ",error.message) return reject(error); } }) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 72d7d7b5..6e3404f8 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -22,7 +22,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); - +const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); module.exports = class ProjectTemplatesHelper { @@ -1048,6 +1048,19 @@ module.exports = class ProjectTemplatesHelper { message :CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND } } + if ( templateData[0].certificateTemplateId && templateData[0].certificateTemplateId !== "" ){ + let certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : templateData[0].certificateTemplateId + },["criteria"]); + + //certificate template data do not exists. + if ( !certificateTemplateDetails.length > 0 ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND + }; + } + templateData[0].criteria = certificateTemplateDetails[0].criteria + } if (templateData[0].tasks && templateData[0].tasks.length > 0) { templateData[0].tasks = diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index f4dee69a..2bcd193a 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -144,7 +144,7 @@ module.exports = class UserProjectsHelper { } const projectsModel = Object.keys(schemas["projects"].schema); - + let keysToRemoveFromUpdation = ["userRoleInformation","userProfile","certificate"] keysToRemoveFromUpdation.forEach( key => { if (data[key])delete data[key]; @@ -2480,7 +2480,7 @@ module.exports = class UserProjectsHelper { recipient : { id : data.userId, name : data.userProfile.userName, - type : data.userProfile.userType + type : data.userProfile.profileUserType.type }, templateUrl : data.certificate.templateUrl, issuer : certificateTemplateDetails[0].issuer, From 785afe5be324345435568a168c0292ed14350d20 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 25 Nov 2022 17:49:14 +0530 Subject: [PATCH 202/373] console change --- generics/services/certificate.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/generics/services/certificate.js b/generics/services/certificate.js index b11d7b07..7620cc35 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -40,9 +40,9 @@ const createCertificate = function (bodyData) { let result = { success : true }; - console.log("line 41 error from RC call error :",err.message); if (err) { result.success = false; + console.log("line 45 error from RC call error :",err.message); } else { let response = data.body; console.log("certificate success response: ",response) @@ -90,8 +90,9 @@ const getCertificateIssuerKid = function () { let result = { success : true }; - console.log("KID rc call error : ",err.message) + if (err) { + console.log("KID rc call error : ",err.message) result.success = false; } else { let response = data.body; From 63dd62f82b9efe618f6ec1a7604542886daaf733 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Mon, 28 Nov 2022 17:19:47 +0530 Subject: [PATCH 203/373] Make logs as a string. --- generics/services/certificate.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 7620cc35..42f75a15 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -32,7 +32,7 @@ const createCertificate = function (bodyData) { json : bodyData }; console.log("requestUrlcertificate create : ",certificateCreateUrl) - console.log("certificateRequestBody : ",bodyData) + console.log("certificateRequestBody : ",JSON.stringify(bodyData)) request.post(certificateCreateUrl,options,certificateCallback); function certificateCallback(err, data) { @@ -45,7 +45,7 @@ const createCertificate = function (bodyData) { console.log("line 45 error from RC call error :",err.message); } else { let response = data.body; - console.log("certificate success response: ",response) + console.log("certificate success response: ",JSON.stringify(response)) if( response.params.status === "SUCCESSFUL" ) { result["data"] = response.result; } else { @@ -84,7 +84,7 @@ const getCertificateIssuerKid = function () { json : bodyData }; console.log("issuer Kid url : ",issuerKidUrl); - console.log("issuer Kid bodyData : ",bodyData); + console.log("issuer Kid bodyData : ",JSON.stringify(bodyData)); request.post(issuerKidUrl,options,getKidCallback); function getKidCallback(err, data) { let result = { @@ -96,7 +96,7 @@ const getCertificateIssuerKid = function () { result.success = false; } else { let response = data.body; - console.log("KID success response : ",response) + console.log("KID success response : ",JSON.stringify(response)) if( response.length > 0 && response[0].osid && response[0].osid !== "" ) { result["data"] = response[0].osid; } else { From 31c8b7e381dd021a302e2a77292d98a8fd5feba6 Mon Sep 17 00:00:00 2001 From: Akash Shah Date: Mon, 28 Nov 2022 17:38:48 +0530 Subject: [PATCH 204/373] Log raw data. --- generics/services/certificate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 42f75a15..7538eaeb 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -36,7 +36,7 @@ const createCertificate = function (bodyData) { request.post(certificateCreateUrl,options,certificateCallback); function certificateCallback(err, data) { - + console.log("line 39 raw data from RC call :",JSON.stringify(data)); let result = { success : true }; From 290753284f0a75a8bdd63f7074dbcd696d1efc14 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 2 Dec 2022 17:06:42 +0530 Subject: [PATCH 205/373] certificate creation sync mode enabled --- generics/constants/endpoints.js | 2 +- generics/services/certificate.js | 8 ++++---- module/userProjects/helper.js | 12 +++++++----- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 14509493..c8a5bfaf 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -49,7 +49,7 @@ module.exports = { USER_READ_V5 : "/v5/user/read", GET_LOCATION_DATA : "/v1/location/search", CERTIFICATE_CREATE : "/api/v1/ProjectCertificate", - PROJECT_CERTIFICATE_API_CALLBACK : "/v1/userProject/certificateCallback", + PROJECT_CERTIFICATE_API_CALLBACK : "/v1/userProjects/certificateCallback", USER_READ_PRIVATE : "/private/user/v1/read", // !Caution: End point for reading user details without token. Do not use for public work flow GET_CERTIFICATE_KID : "/api/v1/PublicKey/search" }; diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 7620cc35..01f7b110 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -21,18 +21,18 @@ const createCertificate = function (bodyData) { try { const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; - const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; + // const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; let certificateCreateUrl = process.env.CERTIFICATE_SERVICE_URL + - CONSTANTS.endpoints.CERTIFICATE_CREATE + "?mode=async&callback=" + callbackUrl; + CONSTANTS.endpoints.CERTIFICATE_CREATE //+ "?mode=async&callback=" + callbackUrl; const options = { headers : { "content-type": "application/json" }, json : bodyData }; - console.log("requestUrlcertificate create : ",certificateCreateUrl) - console.log("certificateRequestBody : ",bodyData) + console.log("bodyData : ",bodyData) + console.log("certificateCreateUrl : ",certificateCreateUrl) request.post(certificateCreateUrl,options,certificateCallback); function certificateCallback(err, data) { diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 2bcd193a..19eb734c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2372,7 +2372,7 @@ module.exports = class UserProjectsHelper { // create payload for certificate generation const certificateData = await this.createCertificatePayload(data); - + // call sunbird-RC to create certificate for project const certificate = await this.createCertificate(certificateData, data._id) @@ -2518,7 +2518,8 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { - const certificateDetails = await certificateService.createCertificate( certificateData ); + const certificateDetails = await certificateService.createCertificate( certificateData ); + if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { throw { message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED @@ -2552,14 +2553,15 @@ module.exports = class UserProjectsHelper { updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; } updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date();; - + if ( Object.keys(updateObject["$set"]).length > 0 ) { - await projectQueries.findOneAndUpdate( + let updatedProject = await projectQueries.findOneAndUpdate( { _id: projectId }, updateObject ); + await kafkaProducersHelper.pushProjectToKafka(updatedProject); } return resolve( { success: true @@ -2615,7 +2617,7 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND } } - + await kafkaProducersHelper.pushProjectToKafka(projectDetails); return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, From ca40f5ed98d3764668711c99c4e0354482315ac5 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 5 Dec 2022 11:59:13 +0530 Subject: [PATCH 206/373] issuedOn key added for sync mode --- module/userProjects/helper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 19eb734c..0b77dabf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2551,6 +2551,7 @@ module.exports = class UserProjectsHelper { certificateDetails.data.ProjectCertificate.osid !== "" ) { updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; + updateObject["$set"]["certificate.issuedOn"] = new Date(); } updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date();; From f715e06e789463097a7788f4053336d97afcfe10 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 12 Dec 2022 12:13:57 +0530 Subject: [PATCH 207/373] async mode enabled, certificate list change to pass complete templateUrl --- generics/services/certificate.js | 4 ++-- module/userProjects/helper.js | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 01f7b110..1eeb6289 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -21,10 +21,10 @@ const createCertificate = function (bodyData) { try { const ML_PROJECT_URL = `http://${process.env.SERVICE_NAME}:${process.env.APPLICATION_PORT}`; - // const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; + const callbackUrl = ML_PROJECT_URL + CONSTANTS.endpoints.PROJECT_CERTIFICATE_API_CALLBACK; let certificateCreateUrl = process.env.CERTIFICATE_SERVICE_URL + - CONSTANTS.endpoints.CERTIFICATE_CREATE //+ "?mode=async&callback=" + callbackUrl; + CONSTANTS.endpoints.CERTIFICATE_CREATE + "?mode=async&callback=" + callbackUrl; const options = { headers : { "content-type": "application/json" diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 0b77dabf..f0aa3c7e 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2674,6 +2674,28 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND } } + //loop through user projects and get downloadable url for templateUrl if osid is present. + for( let userProjectPointer = 0; userProjectPointer < userProject.length; userProjectPointer++ ) { + if ( userProject[userProjectPointer].certificate.osid && + userProject[userProjectPointer].certificate.osid !== "" && + userProject[userProjectPointer].certificate.templateUrl && + userProject[userProjectPointer].certificate.templateUrl !== "" + ){ + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [userProject[userProjectPointer].certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + userProject[userProjectPointer].certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; + } else { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; + } + } + } let count = _.countBy(userProject, (rec) => { return (rec.certificate && rec.certificate.osid && rec.certificate.osid !== "" )? 'generated': 'notGenerated'; From a1136c191b7834968dd321deba76b8ec61904af9 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 12 Dec 2022 13:37:32 +0530 Subject: [PATCH 208/373] code optimized- downloadable templateUrl --- module/userProjects/helper.js | 40 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index f0aa3c7e..ab51762d 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2674,28 +2674,40 @@ module.exports = class UserProjectsHelper { message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND } } + let templateFilePath = []; //loop through user projects and get downloadable url for templateUrl if osid is present. for( let userProjectPointer = 0; userProjectPointer < userProject.length; userProjectPointer++ ) { if ( userProject[userProjectPointer].certificate.osid && userProject[userProjectPointer].certificate.osid !== "" && userProject[userProjectPointer].certificate.templateUrl && userProject[userProjectPointer].certificate.templateUrl !== "" - ){ - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: [userProject[userProjectPointer].certificate.templateUrl] - } - ); - if ( certificateTemplateDownloadableUrl.success ) { - userProject[userProjectPointer].certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; - } else { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND - }; - } + ) { + templateFilePath.push(userProject[userProjectPointer].certificate.templateUrl); } } + + if( templateFilePath.length > 0 ) { + + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: templateFilePath + } + ); + if ( !certificateTemplateDownloadableUrl.success ) { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; + } + // map downloadable templateUrl to corresponding project data + userProject.forEach(projectData => { + var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find(item=> item.filePath == projectData.certificate.templateUrl); + if (itemFromUrlArray) { + projectData.certificate.templateUrl = itemFromUrlArray.url; + } + } + ) + } let count = _.countBy(userProject, (rec) => { return (rec.certificate && rec.certificate.osid && rec.certificate.osid !== "" )? 'generated': 'notGenerated'; From 9f694a566afb507cacfdb40fddd5f21ff4ff4adc Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 12 Dec 2022 15:34:01 +0530 Subject: [PATCH 209/373] generate complete templateUrl capability added to userAssigned fn --- module/userProjects/helper.js | 45 ++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index ab51762d..fcf67ea1 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1927,7 +1927,7 @@ module.exports = class UserProjectsHelper { query["referenceFrom"] = CONSTANTS.common.LINK; } } - + let projects = await this.projects( query, pageSize, @@ -1948,7 +1948,7 @@ module.exports = class UserProjectsHelper { "certificate" ] ); - + let totalCount = 0; let data = []; @@ -1956,9 +1956,11 @@ module.exports = class UserProjectsHelper { totalCount = projects.data.count; data = projects.data.data; - + if( data.length > 0 ) { + let templateFilePath = []; data.forEach( projectData => { + projectData.name = projectData.title; @@ -1974,7 +1976,44 @@ module.exports = class UserProjectsHelper { projectData.type = CONSTANTS.common.IMPROVEMENT_PROJECT; delete projectData.title; + + if (projectData.certificate && + projectData.certificate.osid && + projectData.certificate.osid !== "" && + projectData.certificate.templateUrl && + projectData.certificate.templateUrl !== "" + ) { + templateFilePath.push(projectData.certificate.templateUrl); + } + }); + + if( templateFilePath.length > 0 ) { + + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: templateFilePath + } + ); + if ( !certificateTemplateDownloadableUrl.success ) { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; + } + // map downloadable templateUrl to corresponding project data + data.forEach(projectData => { + if (projectData.certificate) { + var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find(item=> item.filePath == projectData.certificate.templateUrl); + if (itemFromUrlArray) { + projectData.certificate.templateUrl = itemFromUrlArray.url; + } + } + } + + ) + } + } } From 9c16a6bff58e817c3d1d5b878510ea145d333c55 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 12 Dec 2022 18:13:22 +0530 Subject: [PATCH 210/373] consoles removed --- envVariables.js | 2 +- generics/services/certificate.js | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/envVariables.js b/envVariables.js index 13ef9826..ef6073d8 100644 --- a/envVariables.js +++ b/envVariables.js @@ -44,7 +44,7 @@ let enviromentVariables = { "SERVICE_NAME" : { "message" : "current service name", "optional" : true, - "default" : "ml-project-service" + "default" : "ml-projects-service" }, "CERTIFICATE_SERVICE_URL" : { "message" : "certificate service base url", diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 3bd0f997..446333f1 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -32,22 +32,16 @@ const createCertificate = function (bodyData) { json : bodyData }; - console.log("bodyData : ",bodyData) - console.log("certificateCreateUrl : ",certificateCreateUrl) - request.post(certificateCreateUrl,options,certificateCallback); function certificateCallback(err, data) { - console.log("line 39 raw data from RC call :",JSON.stringify(data)); let result = { success : true }; if (err) { result.success = false; - console.log("line 45 error from RC call error :",err.message); } else { let response = data.body; - console.log("certificate success response: ",JSON.stringify(response)) if( response.params.status === "SUCCESSFUL" ) { result["data"] = response.result; } else { @@ -58,7 +52,6 @@ const createCertificate = function (bodyData) { } } catch (error) { - console.log("line 58 catch block : ",error.message) return reject(error); } }) @@ -85,8 +78,6 @@ const getCertificateIssuerKid = function () { }, json : bodyData }; - console.log("issuer Kid url : ",issuerKidUrl); - console.log("issuer Kid bodyData : ",JSON.stringify(bodyData)); request.post(issuerKidUrl,options,getKidCallback); function getKidCallback(err, data) { let result = { @@ -94,11 +85,9 @@ const getCertificateIssuerKid = function () { }; if (err) { - console.log("KID rc call error : ",err.message) result.success = false; } else { let response = data.body; - console.log("KID success response : ",JSON.stringify(response)) if( response.length > 0 && response[0].osid && response[0].osid !== "" ) { result["data"] = response[0].osid; } else { @@ -114,7 +103,6 @@ const getCertificateIssuerKid = function () { }, CONSTANTS.common.SERVER_TIME_OUT); } catch (error) { - console.log("catch error : ",error.message) return reject(error); } }) From 89cfb4c877b8e588ed97b501d9c4f1273b9cc51f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 12 Dec 2022 18:28:17 +0530 Subject: [PATCH 211/373] console removed --- generics/services/certificate.js | 12 ++++++++++++ generics/services/report.js | 3 --- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 446333f1..3bd0f997 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -32,16 +32,22 @@ const createCertificate = function (bodyData) { json : bodyData }; + console.log("bodyData : ",bodyData) + console.log("certificateCreateUrl : ",certificateCreateUrl) + request.post(certificateCreateUrl,options,certificateCallback); function certificateCallback(err, data) { + console.log("line 39 raw data from RC call :",JSON.stringify(data)); let result = { success : true }; if (err) { result.success = false; + console.log("line 45 error from RC call error :",err.message); } else { let response = data.body; + console.log("certificate success response: ",JSON.stringify(response)) if( response.params.status === "SUCCESSFUL" ) { result["data"] = response.result; } else { @@ -52,6 +58,7 @@ const createCertificate = function (bodyData) { } } catch (error) { + console.log("line 58 catch block : ",error.message) return reject(error); } }) @@ -78,6 +85,8 @@ const getCertificateIssuerKid = function () { }, json : bodyData }; + console.log("issuer Kid url : ",issuerKidUrl); + console.log("issuer Kid bodyData : ",JSON.stringify(bodyData)); request.post(issuerKidUrl,options,getKidCallback); function getKidCallback(err, data) { let result = { @@ -85,9 +94,11 @@ const getCertificateIssuerKid = function () { }; if (err) { + console.log("KID rc call error : ",err.message) result.success = false; } else { let response = data.body; + console.log("KID success response : ",JSON.stringify(response)) if( response.length > 0 && response[0].osid && response[0].osid !== "" ) { result["data"] = response[0].osid; } else { @@ -103,6 +114,7 @@ const getCertificateIssuerKid = function () { }, CONSTANTS.common.SERVER_TIME_OUT); } catch (error) { + console.log("catch error : ",error.message) return reject(error); } }) diff --git a/generics/services/report.js b/generics/services/report.js index 765e9ea7..75e58b9a 100644 --- a/generics/services/report.js +++ b/generics/services/report.js @@ -118,8 +118,6 @@ const projectAndTaskReport = function (token, input, projectPdf) { const url = reportsUrl + CONSTANTS.endpoints.PROJECT_AND_TASK_REPORT + "?projectPdf=" + projectPdf; - - console.log("--- url is- ----",url); let options = { headers : { @@ -147,7 +145,6 @@ const projectAndTaskReport = function (token, input, projectPdf) { } } catch (error) { - console.log("catch error",error); return reject(error); } }) From 747b8f696d1385fa8e9e8672cc62c6995d2e8bf3 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 13:04:10 +0530 Subject: [PATCH 212/373] removed global varaiable assign and check of issuer kid --- envVariables.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/envVariables.js b/envVariables.js index ef6073d8..013e7547 100644 --- a/envVariables.js +++ b/envVariables.js @@ -49,7 +49,7 @@ let enviromentVariables = { "CERTIFICATE_SERVICE_URL" : { "message" : "certificate service base url", "optional" : true, - "default" : "http://registry-service:8081", + "default" : "http://11.3.8.129/registry-service", "requiredIf" : { "key": "PROJECT_CERTIFICATE_ON_OFF", "operator" : "EQUALS", @@ -150,10 +150,11 @@ async function getKid(){ // get certificate issuer kid from sunbird-RC let kidData = await certificateService.getCertificateIssuerKid(); if( !kidData.success ) { - console.log("Server stoped . Failed to set certificate issuer Kid value") - process.exit(); + console.log("failed to get kid value from registry service") + // console.log("Server stoped . Failed to set certificate issuer Kid value") + // process.exit(); } - global.CERTIFICATE_ISSUER_KID = kidData.data + // global.CERTIFICATE_ISSUER_KID = kidData.data } }; From 3f326f4f409a104eb23fcd39da8e82be9ecede20 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 13:08:19 +0530 Subject: [PATCH 213/373] chenge in envVariables --- envVariables.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/envVariables.js b/envVariables.js index 013e7547..df8525ca 100644 --- a/envVariables.js +++ b/envVariables.js @@ -49,7 +49,7 @@ let enviromentVariables = { "CERTIFICATE_SERVICE_URL" : { "message" : "certificate service base url", "optional" : true, - "default" : "http://11.3.8.129/registry-service", + "default" : "http://registry-service:8081", "requiredIf" : { "key": "PROJECT_CERTIFICATE_ON_OFF", "operator" : "EQUALS", From e5754ba510aab3f94fefa6bf11e6c572db5bd7d9 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 15:19:50 +0530 Subject: [PATCH 214/373] console added to check issue --- controllers/v1/userProjects.js | 2 ++ envVariables.js | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index cc904bef..e674ed07 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1104,6 +1104,8 @@ module.exports = class UserProjects extends Abstract { return new Promise(async (resolve, reject) => { try { // ReIssue certificate of given project : projectId is passed as param + // This console has to be removed- adding to check the Issuer kid value in case rancher doesn't display console while deployment + console.log("+++++CERTIFICATE_ISSUER_KID+++++ : ",CERTIFICATE_ISSUER_KID) let projectDetails = await userProjectsHelper.certificateReIssue( req.params._id, ); diff --git a/envVariables.js b/envVariables.js index df8525ca..f828914a 100644 --- a/envVariables.js +++ b/envVariables.js @@ -150,9 +150,12 @@ async function getKid(){ // get certificate issuer kid from sunbird-RC let kidData = await certificateService.getCertificateIssuerKid(); if( !kidData.success ) { - console.log("failed to get kid value from registry service") + console.log("failed to get kid value from registry service : ",kidData) // console.log("Server stoped . Failed to set certificate issuer Kid value") // process.exit(); + } else { + console.log("Kid data fetched successfully : ",kidData.data) + global.CERTIFICATE_ISSUER_KID = kidData.data } // global.CERTIFICATE_ISSUER_KID = kidData.data } From c0b83ba17ebb696f6c2b9eb89bc37bbafbf93fb3 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 15:42:13 +0530 Subject: [PATCH 215/373] console added to debug --- envVariables.js | 1 + 1 file changed, 1 insertion(+) diff --git a/envVariables.js b/envVariables.js index f828914a..a36d5e04 100644 --- a/envVariables.js +++ b/envVariables.js @@ -157,6 +157,7 @@ async function getKid(){ console.log("Kid data fetched successfully : ",kidData.data) global.CERTIFICATE_ISSUER_KID = kidData.data } + console.log(JSON.stringify(kidData)) // global.CERTIFICATE_ISSUER_KID = kidData.data } }; From 95a4dee62f3175c83519fd5a230ef3e22009900b Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 16:46:42 +0530 Subject: [PATCH 216/373] console is added to check callback call, kafka condition added to avoid looping --- generics/kafka/consumers/projectCertificate.js | 3 ++- module/userProjects/helper.js | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/generics/kafka/consumers/projectCertificate.js b/generics/kafka/consumers/projectCertificate.js index 69389e77..bdb28983 100644 --- a/generics/kafka/consumers/projectCertificate.js +++ b/generics/kafka/consumers/projectCertificate.js @@ -23,7 +23,8 @@ var messageReceived = function (message) { let parsedMessage = JSON.parse( message.value ); if ( parsedMessage.status == CONSTANTS.common.SUBMITTED_STATUS && parsedMessage.certificate && - Object.keys(parsedMessage.certificate).length > 0 + Object.keys(parsedMessage.certificate).length > 0 && + !parsedMessage.certificate.osid ) { await userProjectsHelper.generateCertificate( parsedMessage ); } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index fcf67ea1..0d7e5b74 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2628,6 +2628,11 @@ module.exports = class UserProjectsHelper { static certificateCallback(transactionId, osid) { return new Promise(async (resolve, reject) => { try { + // adding comments to check call back is called properly or not + console.log("<==================callback called====================>",transactionId,osid) + console.log("transactionId :",transactionId) + console.log("osid :",osid) + console.log("<==================callback called====================>") // callback request structure nested so validating transactionId and osid here instead in validator. if ( transactionId == "" || osid == "" ) { throw { From c042ad250f92a24d30f8ee073bb0b798da158dc4 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 16:59:39 +0530 Subject: [PATCH 217/373] kafka consumer check for eligible key absent added --- generics/kafka/consumers/projectCertificate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/kafka/consumers/projectCertificate.js b/generics/kafka/consumers/projectCertificate.js index bdb28983..66823a75 100644 --- a/generics/kafka/consumers/projectCertificate.js +++ b/generics/kafka/consumers/projectCertificate.js @@ -24,7 +24,7 @@ var messageReceived = function (message) { if ( parsedMessage.status == CONSTANTS.common.SUBMITTED_STATUS && parsedMessage.certificate && Object.keys(parsedMessage.certificate).length > 0 && - !parsedMessage.certificate.osid + !parsedMessage.certificate.eligible ) { await userProjectsHelper.generateCertificate( parsedMessage ); } From fb4fe9d2a0bbdd0849b9f616ab106e7114c201bf Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 17:39:54 +0530 Subject: [PATCH 218/373] console added to check callback && updated rc response check condition --- controllers/v1/userProjects.js | 2 ++ generics/services/certificate.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index e674ed07..052a4f9b 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -997,6 +997,8 @@ module.exports = class UserProjects extends Abstract { async certificateCallback(req) { return new Promise(async (resolve, reject) => { try { + //console request body to check if callback is coming or not and to check any structural change is there or not + console.log("-------------callback request body------------",JSON.stringify(req.body)) let certificateDetails = await userProjectsHelper.certificateCallback( req.body.data.transactionId, req.body.data.osid ); return resolve({ message: certificateDetails.message, diff --git a/generics/services/certificate.js b/generics/services/certificate.js index 3bd0f997..6fd193c6 100644 --- a/generics/services/certificate.js +++ b/generics/services/certificate.js @@ -48,7 +48,7 @@ const createCertificate = function (bodyData) { } else { let response = data.body; console.log("certificate success response: ",JSON.stringify(response)) - if( response.params.status === "SUCCESSFUL" ) { + if( response.params && response.params.status && response.params.status === "SUCCESSFUL" ) { result["data"] = response.result; } else { result.success = false; From 8b3de75febf4aa5c1326574e479f019dc7dfd6a4 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 13 Dec 2022 21:38:23 +0530 Subject: [PATCH 219/373] kafka push for sync mode removed --- generics/constants/api-responses.js | 3 ++- module/userProjects/helper.js | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 0ce30788..7404a87a 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -133,5 +133,6 @@ module.exports = { "CERTIFICATE_TEMPLATE_NOT_FOUND" : "Certificate template details not found", "CERTIFICATE_GENERATION_FAILED" : "Certificate generation failed", "NOT_ELIGIBLE_FOR_CERTIFICATE" : "Project is not eligible for certificate", - "ISSUER_KID_NOT_FOUND" : "Failed to fetch certificate issuer kid" + "ISSUER_KID_NOT_FOUND" : "Failed to fetch certificate issuer kid", + "PROJECT_SUBMITTED_FOR_REISSUE" : "Submitted for project certificate reIssue" }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 0d7e5b74..f1ba9f0c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2601,7 +2601,6 @@ module.exports = class UserProjectsHelper { }, updateObject ); - await kafkaProducersHelper.pushProjectToKafka(updatedProject); } return resolve( { success: true @@ -2850,7 +2849,7 @@ module.exports = class UserProjectsHelper { return resolve({ success: true, - message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, + message: CONSTANTS.apiResponses.PROJECT_SUBMITTED_FOR_REISSUE, data : { _id : userProject[0]._id } From 691259b2bb8a01176b0727f5e5e4037a08276270 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 15 Dec 2022 12:33:16 +0530 Subject: [PATCH 220/373] guest access path updated with certificateCallback --- generics/middleware/authenticator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index b3599204..b34628ab 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -49,7 +49,7 @@ module.exports = async function (req, res, next, token = "") { // Allow search endpoints for non-logged in users. let guestAccess = false; - let guestAccessPaths = ["/dataPipeline/","/templates/details"]; + let guestAccessPaths = ["/dataPipeline/","/templates/details","userProjects/certificateCallback"]; await Promise.all(guestAccessPaths.map(async function (path) { if (req.path.includes(path)) { guestAccess = true; From 88e5586b5fa71775b8fe3555479daf68e6187b4e Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 20 Dec 2022 17:17:37 +0530 Subject: [PATCH 221/373] referenceId added to project tasks --- module/certificateValidations/helper.js | 6 +++--- module/userProjects/helper.js | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/module/certificateValidations/helper.js b/module/certificateValidations/helper.js index fc9a7a32..82a591cb 100644 --- a/module/certificateValidations/helper.js +++ b/module/certificateValidations/helper.js @@ -152,12 +152,12 @@ function _validateCriteriaConditions(condition, data) { } } else if ( projectTasks && projectTasks.length > 0 && condition.taskDetails.length > 0 ) { - - // specific task Id or Ids are passed for attachment validation + + // specific task Id( from projectTemplates ) or Ids are passed for attachment validation for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { for ( let taskDetailsPointer = 0; taskDetailsPointer < condition.taskDetails.length; taskDetailsPointer++ ) { // get attachments data of specified task/ tasks - if ( projectTasks[tasksIndex]._id == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { + if ( projectTasks[tasksIndex].referenceId == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) } } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index f1ba9f0c..6393859d 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -379,6 +379,7 @@ module.exports = class UserProjectsHelper { status: HTTP_STATUS_CODE['bad_request'].status } } + // push project details to kafka await kafkaProducersHelper.pushProjectToKafka(projectUpdated); @@ -1376,7 +1377,6 @@ module.exports = class UserProjectsHelper { static userAssignedProjectCreation(templateId, userId, userToken) { return new Promise(async (resolve, reject) => { try { - const projectTemplateData = await projectTemplateQueries.templateDocument({ status: CONSTANTS.common.PUBLISHED, @@ -1415,7 +1415,7 @@ module.exports = class UserProjectsHelper { await projectTemplatesHelper.tasksAndSubTasks( projectTemplateData[0]._id ); - + if (tasksAndSubTasks.length > 0) { result.tasks = _projectTask(tasksAndSubTasks); @@ -3130,6 +3130,7 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { singleTask.isDeletable = true; } + singleTask.referenceId = singleTask._id; singleTask.createdAt = singleTask.createdAt ? singleTask.createdAt : new Date(); singleTask.updatedAt = new Date(); singleTask._id = UTILS.isValidMongoId(singleTask._id.toString()) ? uuidv4() : singleTask._id; From c4bdbcf5710e3c10e75064d18bf6c2545f771f8b Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 21 Dec 2022 13:13:39 +0530 Subject: [PATCH 222/373] comparing with task externalId --- module/certificateValidations/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/certificateValidations/helper.js b/module/certificateValidations/helper.js index 82a591cb..e1d0df51 100644 --- a/module/certificateValidations/helper.js +++ b/module/certificateValidations/helper.js @@ -157,7 +157,7 @@ function _validateCriteriaConditions(condition, data) { for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { for ( let taskDetailsPointer = 0; taskDetailsPointer < condition.taskDetails.length; taskDetailsPointer++ ) { // get attachments data of specified task/ tasks - if ( projectTasks[tasksIndex].referenceId == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { + if ( projectTasks[tasksIndex].externalId == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) } } From 141ceafcb0df875c631c576599d96a026f02dfc1 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 21 Dec 2022 13:50:49 +0530 Subject: [PATCH 223/373] refereceid key removed --- module/userProjects/helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6393859d..cb0daa73 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3130,7 +3130,6 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { singleTask.isDeletable = true; } - singleTask.referenceId = singleTask._id; singleTask.createdAt = singleTask.createdAt ? singleTask.createdAt : new Date(); singleTask.updatedAt = new Date(); singleTask._id = UTILS.isValidMongoId(singleTask._id.toString()) ? uuidv4() : singleTask._id; From 947d9a99e7455651176f34d56f60311e3b6d4bf6 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 21 Dec 2022 15:59:58 +0530 Subject: [PATCH 224/373] reference id replacement issue resolved --- module/certificateValidations/helper.js | 2 +- module/userProjects/helper.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/module/certificateValidations/helper.js b/module/certificateValidations/helper.js index e1d0df51..82a591cb 100644 --- a/module/certificateValidations/helper.js +++ b/module/certificateValidations/helper.js @@ -157,7 +157,7 @@ function _validateCriteriaConditions(condition, data) { for ( let tasksIndex = 0; tasksIndex < projectTasks.length; tasksIndex++ ) { for ( let taskDetailsPointer = 0; taskDetailsPointer < condition.taskDetails.length; taskDetailsPointer++ ) { // get attachments data of specified task/ tasks - if ( projectTasks[tasksIndex].externalId == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { + if ( projectTasks[tasksIndex].referenceId == condition.taskDetails[taskDetailsPointer] && projectTasks[tasksIndex][condition.key] && projectTasks[tasksIndex][condition.key].length > 0 ) { tasksAttachments.push(...projectTasks[tasksIndex][condition.key]) } } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index cb0daa73..1490327d 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3120,7 +3120,7 @@ function _attachmentInformation ( attachmentWithSourcePath = [], linkAttachments function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { tasks.forEach(singleTask => { - + singleTask.externalId = singleTask.externalId ? singleTask.externalId : singleTask.name.toLowerCase(); singleTask.type = singleTask.type ? singleTask.type : CONSTANTS.common.SIMPLE_TASK_TYPE; singleTask.status = singleTask.status ? singleTask.status : CONSTANTS.common.NOT_STARTED_STATUS; @@ -3129,7 +3129,9 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { if (!singleTask.hasOwnProperty("isDeletable")) { singleTask.isDeletable = true; } - + if ( UTILS.isValidMongoId(singleTask._id.toString()) ) { + singleTask.referenceId = singleTask._id; + } singleTask.createdAt = singleTask.createdAt ? singleTask.createdAt : new Date(); singleTask.updatedAt = new Date(); singleTask._id = UTILS.isValidMongoId(singleTask._id.toString()) ? uuidv4() : singleTask._id; @@ -3168,7 +3170,7 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { } }) - + return tasks; } From a138d29a6f2fe7a5d173feb64dd39f3274e71a09 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 21 Dec 2022 16:19:59 +0530 Subject: [PATCH 225/373] referenceId replacement fix --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1490327d..329c9927 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -121,6 +121,7 @@ module.exports = class UserProjectsHelper { "appInformation", "status" ]); + if (!userProject.length > 0) { throw { @@ -3130,7 +3131,7 @@ function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { singleTask.isDeletable = true; } if ( UTILS.isValidMongoId(singleTask._id.toString()) ) { - singleTask.referenceId = singleTask._id; + singleTask.referenceId = singleTask._id.toString(); } singleTask.createdAt = singleTask.createdAt ? singleTask.createdAt : new Date(); singleTask.updatedAt = new Date(); From 6c6f0ffcc912e8e64273e453ac26d05cb340941a Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 21 Dec 2022 17:10:18 +0530 Subject: [PATCH 226/373] completedDate added to projection --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 329c9927..fe55695c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2709,7 +2709,8 @@ module.exports = class UserProjectsHelper { "certificate.status", "certificate.eligible", "certificate.message", - "certificate.issuedOn" + "certificate.issuedOn", + "completedDate" ]); if ( !userProject.length > 0 ) { From 5741c0f0c52b6c3d7ca4b5f63a10d1885fc86675 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 28 Dec 2022 19:54:26 +0530 Subject: [PATCH 227/373] console added to check kid issue --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index fe55695c..5929bff9 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2482,7 +2482,7 @@ module.exports = class UserProjectsHelper { static createCertificatePayload(data) { return new Promise(async (resolve, reject) => { try { - + console.log("Certificate issuer Kid: ",CERTIFICATE_ISSUER_KID) // get downloadable url for certificate template if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { let certificateTemplateDownloadableUrl = @@ -2536,6 +2536,7 @@ module.exports = class UserProjectsHelper { return resolve(certificateData); } catch (error) { + console.log("error:",error.message) return resolve({ success: false, message: error.message From 70bf0b5936e0a0efeebec1bc3ff969af4432d9e7 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Wed, 28 Dec 2022 20:08:24 +0530 Subject: [PATCH 228/373] ISSUER_KID check added from env --- envVariables.js | 3 +++ routes/index.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/envVariables.js b/envVariables.js index a36d5e04..307f75b3 100644 --- a/envVariables.js +++ b/envVariables.js @@ -151,6 +151,9 @@ async function getKid(){ let kidData = await certificateService.getCertificateIssuerKid(); if( !kidData.success ) { console.log("failed to get kid value from registry service : ",kidData) + if( process.env.CERTIFICATE_ISSUER_KID && process.env.CERTIFICATE_ISSUER_KID != "" ) { + global.CERTIFICATE_ISSUER_KID = process.env.CERTIFICATE_ISSUER_KID; + } // console.log("Server stoped . Failed to set certificate issuer Kid value") // process.exit(); } else { diff --git a/routes/index.js b/routes/index.js index cad0fe2a..d9ada824 100644 --- a/routes/index.js +++ b/routes/index.js @@ -89,7 +89,7 @@ module.exports = function (app) { } console.log('-------------------Response log starts here-------------------'); - console.log(result); + console.log(JSON.stringify(result)); console.log('-------------------Response log ends here-------------------'); } catch (error) { From 03e9784e2be18398aa76c9685817ca40c1def32c Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 29 Dec 2022 13:37:48 +0530 Subject: [PATCH 229/373] solution model updated --- models/solutions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/models/solutions.js b/models/solutions.js index dacb3a09..536c67c3 100644 --- a/models/solutions.js +++ b/models/solutions.js @@ -97,6 +97,8 @@ module.exports = { default: 1 }, reportInformation : Object, - certificateTemplateId : "ObjectId" + certificateTemplateId : "ObjectId", + rootOrganisations : Array, + createdFor : Array } }; \ No newline at end of file From 53f1db10ec32b6122b095eb4b1fe8a95f7f13cbc Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 3 Jan 2023 12:35:57 +0530 Subject: [PATCH 230/373] setUserProfileInProject migration script added --- .../setUserProfileInProjects.js | 407 ++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 migrations/userProfileAndRoleMismatchInProjects/setUserProfileInProjects.js diff --git a/migrations/userProfileAndRoleMismatchInProjects/setUserProfileInProjects.js b/migrations/userProfileAndRoleMismatchInProjects/setUserProfileInProjects.js new file mode 100644 index 00000000..c739d924 --- /dev/null +++ b/migrations/userProfileAndRoleMismatchInProjects/setUserProfileInProjects.js @@ -0,0 +1,407 @@ +/** + * name : updateUserProfileInProjects.js + * author : Priyanka Pradeep + * created-date : 10-Nov-2022 + * Description : Migration script for update userProfile in project + */ + + const path = require("path"); + let rootPath = path.join(__dirname, '../../') + require('dotenv').config({ path: rootPath+'/.env' }) + + let _ = require("lodash"); + let mongoUrl = process.env.MONGODB_URL; + let dbName = mongoUrl.split("/").pop(); + let url = mongoUrl.split(dbName)[0]; + var MongoClient = require('mongodb').MongoClient; + var ObjectId = require('mongodb').ObjectID; + + var fs = require('fs'); + const request = require('request'); + + const userServiceUrl = "http://learner-service:9000"; + const endPoint = "/v1/location/search"; + const userReadEndpoint = "/private/user/v1/read"; + +(async () => { + + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + + let updatedProjectIds = []; + + //get all projects id where user profile is not there. + let projectDocument = await db.collection('projects').find({ + userRoleInformation: {$exists : true}, + userProfile: {$exists : false}, + }).project({ "_id": 1}).toArray(); + + + let chunkOfProjectDocument = _.chunk(projectDocument, 10); + let projectIds; + + for (let pointerToProject = 0; pointerToProject < chunkOfProjectDocument.length; pointerToProject++) { + + projectIds = await chunkOfProjectDocument[pointerToProject].map( + projectDoc => { + return projectDoc._id; + } + ); + + //get user ids of project without profile + let userIdsWithoutProfile = await db.collection('projects').find({ + _id: { $in : projectIds } + }).project({ + "_id" : 1, + "userId" : 1 + }).toArray(); + + //loop userIds- These user profiles are absent in project + for ( let count = 0; count < userIdsWithoutProfile.length; count++ ) { + + let projectIdWithoutUserProfile = userIdsWithoutProfile[count]._id; + let userId = userIdsWithoutProfile[count].userId; + + //call profile api to get user profile + let profile = await profileReadPrivate(userId); + + // update project with profile + if( profile.success && profile.data && profile.data.response ) { + let updateObject = { + "$set" : {} + }; + updateObject["$set"]["userProfile"] = profile.data.response; + + await db.collection('projects').findOneAndUpdate({ + "_id" : projectIdWithoutUserProfile + },updateObject); + } + + } + + + let projectDocuments = await db.collection('projects').find({ + _id: { $in : projectIds}, + userProfile: {$exists : true} + }).project({ + "_id": 1, + "userRoleInformation" : 1, + "userProfile" : 1 + }).toArray(); + + //loop all projects + for ( let count = 0; count < projectDocuments.length; count++ ) { + + let project = projectDocuments[count]; + let userProfile = project.userProfile; + + + let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles + + if(project.userRoleInformation.role) { // Check if userRoleInformation has role value. + let rolesInUserRoleInformation = project.userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. + + let resetCurrentUserProfileRoles = false; // Flag to reset current userProfile.profileUserTypes i.e. if current role in profile is not at all there in userRoleInformation.roles + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { + + // Loop through current roles in userProfile.profileUserTypes + for (let pointerToCurrentProfileUserTypes = 0; pointerToCurrentProfileUserTypes < userProfile.profileUserTypes.length; pointerToCurrentProfileUserTypes++) { + const currentProfileUserType = userProfile.profileUserTypes[pointerToCurrentProfileUserTypes]; + + if(currentProfileUserType.subType && currentProfileUserType.subType !== null) { // If the role has a subType + + // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!project.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.subType.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } else { // If the role subType is null or is not there + + // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!project.userRoleInformation.role.toUpperCase().includes(currentProfileUserType.type.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } + } + } + if(resetCurrentUserProfileRoles) { // Reset userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + } + + // Loop through each subRole in userRoleInformation + for (let pointerToRolesInUserInformation = 0; pointerToRolesInUserInformation < rolesInUserRoleInformation.length; pointerToRolesInUserInformation++) { + const subRole = rolesInUserRoleInformation[pointerToRolesInUserInformation]; + + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { + if(!_.find(userProfile.profileUserTypes, { 'type': subRole.toLowerCase() }) && !_.find(userProfile.profileUserTypes, { 'subType': subRole.toLowerCase() })) { + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + if(subRole.toUpperCase() === "TEACHER") { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } else { // Make a new entry if userProfile.profileUserTypes is empty or does not exist. + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + if(subRole.toUpperCase() === "TEACHER") { // If subRole is teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } + } + + // Create location only object from userRoleInformation + let userRoleInformationLocationObject = _.omit(project.userRoleInformation, ['role']); + + // All location keys from userRoleInformation + let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); + + let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values + + // Loop through all location keys. + for (let pointerToUserRoleInfromationLocationKeys = 0; pointerToUserRoleInfromationLocationKeys < userRoleInfomrationLocationKeys.length; pointerToUserRoleInfromationLocationKeys++) { + + const locationType = userRoleInfomrationLocationKeys[pointerToUserRoleInfromationLocationKeys]; // e.g. state, district, school + const locationValue = userRoleInformationLocationObject[locationType]; // Location UUID values or school code. + + // Check if userProfile.userLocations exists and is an array of length > 0 + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + + if(locationType === "school") { // If location type school exist check if same is there in userProfile.userLocations + if(!_.find(userProfile.userLocations, { 'type': "school", 'code': locationValue })) { + updateUserProfileLocationInformation = true; // School does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } else { // Check if location type is there in userProfile.userLocations and has same value as userRoleInformation + if(!_.find(userProfile.userLocations, { 'type': locationType, 'id': locationValue })) { + updateUserProfileLocationInformation = true; // Location does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } + } else { + updateUserProfileLocationInformation = true; + break; + } + } + + + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + if(userProfile.userLocations.length != userRoleInfomrationLocationKeys.length) { + updateUserProfileLocationInformation = true; + } + } + + // If userProfile.userLocations has to be updated, get all values and set in userProfile. + if(updateUserProfileLocationInformation) { + + //update userLocations in userProfile + let locationIds = []; + let locationCodes = []; + let userLocations = new Array; + + userRoleInfomrationLocationKeys.forEach( requestedDataKey => { + if (checkIfValidUUID(userRoleInformationLocationObject[requestedDataKey])) { + locationIds.push(userRoleInformationLocationObject[requestedDataKey]); + } else { + locationCodes.push(userRoleInformationLocationObject[requestedDataKey]); + } + }) + + //query for fetch location using id + if ( locationIds.length > 0 ) { + let locationQuery = { + "id" : locationIds + } + + let entityData = await locationSearch(locationQuery); + if ( entityData.success ) { + userLocations = entityData.data; + } + } + + // query for fetch location using code + if ( locationCodes.length > 0 ) { + let codeQuery = { + "code" : locationCodes + } + + let entityData = await locationSearch(codeQuery); + if ( entityData.success ) { + userLocations = userLocations.concat(entityData.data); + } + } + + if ( userLocations.length > 0 ) { + userProfile["userLocations"] = userLocations; + } + } + + + //update projects if userProfile role or location information is incorrect + if ( updateUserProfileRoleInformation || updateUserProfileLocationInformation ) { + + let updateObject = { + "$set" : {} + }; + if(updateUserProfileRoleInformation) { + updateObject["$set"]["userProfile.profileUserTypes"] = userProfile.profileUserTypes; + updateObject["$set"]["userProfile.userRoleMismatchFoundAndUpdated"] = true; + } + if(updateUserProfileLocationInformation) { + updateObject["$set"]["userProfile.userLocations"] = userProfile.userLocations; + updateObject["$set"]["userProfile.userLocationsMismatchFoundAndUpdated"] = true; + } + + await db.collection('projects').findOneAndUpdate({ + "_id" : project._id + },updateObject); + + updatedProjectIds.push(project._id.toString()); + } + + } + + //write updated project ids to file + fs.writeFile( + 'updatedProjectIds.json', + + JSON.stringify(updatedProjectIds), + + function (err) { + if (err) { + console.error('Crap happens'); + } + } + ); + } + + function locationSearch ( filterData ) { + return new Promise(async (resolve, reject) => { + try { + + let bodyData={}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = filterData; + const url = userServiceUrl + endPoint; + const options = { + headers : { + "content-type": "application/json" + }, + json : bodyData + }; + + request.post(url,options,requestCallback); + + let result = { + success : true + }; + + function requestCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = data.body; + if( response.responseCode === "OK" && + response.result && + response.result.response && + response.result.response.length > 0 + ) { + let entityResult = new Array; + response.result.response.map(entityData => { + let entity = _.omit(entityData, ['identifier']); + entityResult.push(entity); + }) + result["data"] = entityResult; + result["count"] = response.result.count; + } else { + result.success = false; + } + } + return resolve(result); + } + + setTimeout(function () { + return resolve (result = { + success : false + }); + }, 5000); + + } catch (error) { + return reject(error); + } + }) + } + + function profileReadPrivate (userId) { + return new Promise(async (resolve, reject) => { + try { + // <--- Important : This url endpoint is private do not use it for regular workflows ---> + let url = userServiceUrl + userReadEndpoint + "/" + userId; + const options = { + headers : { + "content-type": "application/json" + } + }; + request.get(url,options,userReadCallback); + let result = { + success : true + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + + let response = JSON.parse(data.body); + if( response.responseCode === "OK" ) { + result["data"] = response.result; + } else { + result.success = false; + } + + } + return resolve(result); + } + setTimeout(function () { + return resolve (result = { + success : false + }); + }, 5000); + + } catch (error) { + return reject(error); + } + }) + } + + console.log("Updated Project Count : ", updatedProjectIds.length) + console.log("completed") + connection.close(); + } + catch (error) { + console.log(error) + } +})().catch(err => console.error(err)); + +function checkIfValidUUID(value) { + const regexExp = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi; + return regexExp.test(value); +} \ No newline at end of file From 9d3fc2c16791ee5b423403223160e3478572ea59 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 3 Jan 2023 12:58:50 +0530 Subject: [PATCH 231/373] subfolder changed --- .../setUserProfileInProjects.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename migrations/{userProfileAndRoleMismatchInProjects => userProfileAbsentInProjects}/setUserProfileInProjects.js (100%) diff --git a/migrations/userProfileAndRoleMismatchInProjects/setUserProfileInProjects.js b/migrations/userProfileAbsentInProjects/setUserProfileInProjects.js similarity index 100% rename from migrations/userProfileAndRoleMismatchInProjects/setUserProfileInProjects.js rename to migrations/userProfileAbsentInProjects/setUserProfileInProjects.js From d41d3c20c21a548393e47cb91a2e15acc792439a Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 18 Jan 2023 17:45:10 +0530 Subject: [PATCH 232/373] changed from userName to firstName and lastName --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 5929bff9..24887b07 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2519,7 +2519,7 @@ module.exports = class UserProjectsHelper { let certificateData = { recipient : { id : data.userId, - name : data.userProfile.userName, + name : `${data.userProfile.firstName} ${data.userProfile.lastName}`, type : data.userProfile.profileUserType.type }, templateUrl : data.certificate.templateUrl, From a10b6dffe6c60a7746076bb0b7164e7d46bbbd45 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 20 Jan 2023 11:34:21 +0530 Subject: [PATCH 233/373] Fixing reissue certificate --- module/userProjects/helper.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 24887b07..51618b9d 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2813,10 +2813,11 @@ module.exports = class UserProjectsHelper { if ( userProfileData.success && userProfileData.data && userProfileData.data.response && - userProfileData.data.response.userName && - userProfileData.data.response.userName !== "" + userProfileData.data.response.firstName && + userProfileData.data.response.lastName ) { - userProject[0].userProfile.userName = userProfileData.data.response.userName; + userProject[0].userProfile.firstName = userProfileData.data.response.firstName; + userProject[0].userProfile.lastName = userProfileData.data.response.lastName; } else { throw { status: HTTP_STATUS_CODE['bad_request'].status, From 4f7cf552a07ece8b3dcac897be8b32f6940d9f05 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 20 Jan 2023 12:13:20 +0530 Subject: [PATCH 234/373] added only first name in validation --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 51618b9d..1d7cf343 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2814,7 +2814,7 @@ module.exports = class UserProjectsHelper { userProfileData.data && userProfileData.data.response && userProfileData.data.response.firstName && - userProfileData.data.response.lastName + userProfileData.data.response.firstName !== "" ) { userProject[0].userProfile.firstName = userProfileData.data.response.firstName; userProject[0].userProfile.lastName = userProfileData.data.response.lastName; From 33195e6ccfaf490c228b64ddd24d5a25625d0f5b Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 20 Jan 2023 12:53:08 +0530 Subject: [PATCH 235/373] Debug ED-1078 --- module/userProjects/helper.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1d7cf343..9e6072c5 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2810,6 +2810,7 @@ module.exports = class UserProjectsHelper { // fetch user data using userId of project and calling the profile API let userProfileData = await userProfileService.profileReadPrivate(userProject[0].userId); + console.log("userProfileData>>>",JSON.stringify(userProfileData)) if ( userProfileData.success && userProfileData.data && userProfileData.data.response && @@ -2843,6 +2844,15 @@ module.exports = class UserProjectsHelper { if ( userProject[0].certificate.osid ) { updateObject["$set"]["certificate.originalTransactionInformation.osid"] = userProject[0].certificate.osid; } + + if (userProject[0].userProfile.firstName ) { + updateObject["$set"]["userProfile.firstName"] = userProject[0].userProfile.firstName; + } + + if (userProject[0].userProfile.lastName ) { + updateObject["$set"]["userProfile.lastName"] = userProject[0].userProfile.lastName; + } + updateObject["$set"]["certificate.reIssuedAt"] = new Date(); await projectQueries.findOneAndUpdate( { From f95c8ba6ca3acdf6430f1bd254bfe3a716c18caf Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 20 Jan 2023 16:15:40 +0530 Subject: [PATCH 236/373] removed console log --- module/userProjects/helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9e6072c5..839cd416 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2810,7 +2810,6 @@ module.exports = class UserProjectsHelper { // fetch user data using userId of project and calling the profile API let userProfileData = await userProfileService.profileReadPrivate(userProject[0].userId); - console.log("userProfileData>>>",JSON.stringify(userProfileData)) if ( userProfileData.success && userProfileData.data && userProfileData.data.response && From 896993a3bac42fd708564d648df3f660e3ab2498 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 23 Jan 2023 19:11:39 +0530 Subject: [PATCH 237/373] projectName length restricted --- module/userProjects/helper.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 839cd416..fc46cf9b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2483,6 +2483,11 @@ module.exports = class UserProjectsHelper { return new Promise(async (resolve, reject) => { try { console.log("Certificate issuer Kid: ",CERTIFICATE_ISSUER_KID) + + if(data.title.length > 75) { + data.title = data.title.substring(0, 75) + '...'; + } + // get downloadable url for certificate template if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { let certificateTemplateDownloadableUrl = From 4f21926a94cb95542f590b5d989f33dfa59b678d Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 1 Feb 2023 09:12:21 +0530 Subject: [PATCH 238/373] Added Program Join and consent --- controllers/v1/programUsers.js | 22 ++++++++++++ databaseQueries/programUsers.js | 23 ++++++++++++ generics/constants/api-responses.js | 3 +- generics/constants/endpoints.js | 3 +- generics/services/core.js | 56 ++++++++++++++++++++++++++++- models/programUsers.js | 29 +++++++++++++++ module/userProjects/helper.js | 15 +++++++- 7 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 controllers/v1/programUsers.js create mode 100644 databaseQueries/programUsers.js create mode 100644 models/programUsers.js diff --git a/controllers/v1/programUsers.js b/controllers/v1/programUsers.js new file mode 100644 index 00000000..3a9c4923 --- /dev/null +++ b/controllers/v1/programUsers.js @@ -0,0 +1,22 @@ +/** + * name : programUsers.js + * author : Vishnu + * created-date : 9-Jan-2023 + * Description : PII data related controller. +*/ + +/** + * programUsers + * @class + */ +module.exports = class ProgramUsers extends Abstract { + constructor() { + super("programUsers"); + } + + static get name() { + return "programUsers"; + } + +}; + diff --git a/databaseQueries/programUsers.js b/databaseQueries/programUsers.js new file mode 100644 index 00000000..2a8de03f --- /dev/null +++ b/databaseQueries/programUsers.js @@ -0,0 +1,23 @@ +module.exports= class Programs{ + static findProgramJoined(programId,userId) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = { + programId :programId, + userId: userId + } + + + let programJoinedData = + await database.models.programUsers.find( + queryObject, + {} + ).lean(); + return resolve(programJoinedData); + + } catch (error) { + return reject(error); + } + }); + } +} \ No newline at end of file diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 7404a87a..c05d4616 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -134,5 +134,6 @@ module.exports = { "CERTIFICATE_GENERATION_FAILED" : "Certificate generation failed", "NOT_ELIGIBLE_FOR_CERTIFICATE" : "Project is not eligible for certificate", "ISSUER_KID_NOT_FOUND" : "Failed to fetch certificate issuer kid", - "PROJECT_SUBMITTED_FOR_REISSUE" : "Submitted for project certificate reIssue" + "PROJECT_SUBMITTED_FOR_REISSUE" : "Submitted for project certificate reIssue", + "PROGRAM_JOIN_FAILED": "Program Join Failed" }; diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index c8a5bfaf..a42a043a 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -51,5 +51,6 @@ module.exports = { CERTIFICATE_CREATE : "/api/v1/ProjectCertificate", PROJECT_CERTIFICATE_API_CALLBACK : "/v1/userProjects/certificateCallback", USER_READ_PRIVATE : "/private/user/v1/read", // !Caution: End point for reading user details without token. Do not use for public work flow - GET_CERTIFICATE_KID : "/api/v1/PublicKey/search" + GET_CERTIFICATE_KID : "/api/v1/PublicKey/search", + PROGRAM_JOIN: "/v1/programs/join" }; diff --git a/generics/services/core.js b/generics/services/core.js index ec12900e..5851d8e8 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -725,6 +725,59 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution }) } +/** + * program Join Api. + * @function + * @name programJoin + * @param {String} token - User token. + * @param {Object} bodyData - Requested body data. + * @param {String} programId - program id. + * @returns {JSON} - Program Join Status. +*/ +const programJoin = function (programId,bodyData,userToken,appName,appVersion) { + return new Promise(async (resolve, reject) => { + try { + + const url = + ML_CORE_URL + CONSTANTS.endpoints.PROGRAM_JOIN + "/" + programId; + const options = { + headers : { + "content-type": "application/json", + "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, + "x-authenticated-user-token" : userToken, + "x-app-id" :appName, + "x-app-ver":appVersion + }, + json: {userRoleInformation:bodyData} + }; + request.post(url,options,kendraCallback); + + function kendraCallback(err, data) { + + let result = { + success : true + }; + + if (err) { + result.success = false; + } else { + + let response = data.body; + if( response.status === HTTP_STATUS_CODE['ok'].status ) { + result["data"] = response.result; + } else { + result.success = false; + } + } + + return resolve(result); + } + + } catch (error) { + return reject(error); + } + }) +} module.exports = { entityTypesDocuments : entityTypesDocuments, rolesDocuments : rolesDocuments, @@ -738,6 +791,7 @@ module.exports = { createSolution: createSolution, solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, - getDownloadableUrl : getDownloadableUrl + getDownloadableUrl : getDownloadableUrl, + programJoin: programJoin }; diff --git a/models/programUsers.js b/models/programUsers.js new file mode 100644 index 00000000..ed287107 --- /dev/null +++ b/models/programUsers.js @@ -0,0 +1,29 @@ +module.exports = { + name: "programUsers", + schema: { + programId: { + type : "ObjectId", + required: true, + index: true + }, + userId: { + type: String, + index: true + }, + noOfResourcesStarted: { + type:Number, + index: true + }, + userProfile: Object, + userRoleInformation: Object, + appInformation: Object + }, + compoundIndex: [ + { + "name" :{ userId: 1, programId: 1 }, + "indexType" : { unique: true } + } + ] +}; + + \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index fc46cf9b..128952df 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,6 +21,7 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); +const programUsers = require(DB_QUERY_BASE_PATH + "/programUsers"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); @@ -1113,7 +1114,19 @@ module.exports = class UserProjectsHelper { solutionDetails = solutionDetails.data[0]; } - + // program join API call + let programJoined = await programUsers.findProgramJoined(solutionDetails.programId,userId) + + if(programJoined.length == 0){ + let programJoinAPI = await coreService.programJoin(solutionDetails.programId,bodyData,userToken,appName,appVersion) + if(!programJoinAPI.success){ + throw { + success: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + } + } + } + let projectCreation = await this.userAssignedProjectCreation( solutionDetails.projectTemplateId, From 077dd7c33a14343b4d825e72351f2183ecb19c2e Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 1 Feb 2023 12:40:07 +0530 Subject: [PATCH 239/373] Done WIth Project --- generics/constants/api-responses.js | 2 +- generics/services/core.js | 6 ++---- module/userProjects/helper.js | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index c05d4616..db81c809 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -135,5 +135,5 @@ module.exports = { "NOT_ELIGIBLE_FOR_CERTIFICATE" : "Project is not eligible for certificate", "ISSUER_KID_NOT_FOUND" : "Failed to fetch certificate issuer kid", "PROJECT_SUBMITTED_FOR_REISSUE" : "Submitted for project certificate reIssue", - "PROGRAM_JOIN_FAILED": "Program Join Failed" + "PROGRAM_JOIN_FAILED" : "Failed to join program", }; diff --git a/generics/services/core.js b/generics/services/core.js index 5851d8e8..9fe6d6a3 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -734,7 +734,7 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution * @param {String} programId - program id. * @returns {JSON} - Program Join Status. */ -const programJoin = function (programId,bodyData,userToken,appName,appVersion) { +const programJoin = function (programId,bodyData,userToken) { return new Promise(async (resolve, reject) => { try { @@ -745,10 +745,8 @@ const programJoin = function (programId,bodyData,userToken,appName,appVersion) { "content-type": "application/json", "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, "x-authenticated-user-token" : userToken, - "x-app-id" :appName, - "x-app-ver":appVersion }, - json: {userRoleInformation:bodyData} + json: bodyData }; request.post(url,options,kendraCallback); diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 128952df..13d57e28 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1118,15 +1118,25 @@ module.exports = class UserProjectsHelper { let programJoined = await programUsers.findProgramJoined(solutionDetails.programId,userId) if(programJoined.length == 0){ - let programJoinAPI = await coreService.programJoin(solutionDetails.programId,bodyData,userToken,appName,appVersion) - if(!programJoinAPI.success){ - throw { - success: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + if ( appVersion !== "" && appVersion < 5.2 ) { + let programJoinBody = {}; + programJoinBody.userRoleInformation = req.body.userRoleInformation; + programJoinBody.isResource = true; + let joinProgramData = await coreService.programJoin ( + solutionDetails.programId, + programJoinData, + req.userDetails.userToken + ); + + if ( !joinProgramData.success ) { + return resolve({ + status: httpStatusCode.bad_request.status, + message: messageConstants.apiResponses.PROGRAM_JOIN_FAILED + }); } } } - + let projectCreation = await this.userAssignedProjectCreation( solutionDetails.projectTemplateId, From c50395f61fccad153325c41fec24078f7b2b8baa Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 1 Feb 2023 18:36:09 +0530 Subject: [PATCH 240/373] Added Project Update Script --- .../updatePrivateProgramInProject.js | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 migrations/privateProgramInProjects/updatePrivateProgramInProject.js diff --git a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js new file mode 100644 index 00000000..b7763913 --- /dev/null +++ b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js @@ -0,0 +1,152 @@ +/** + * name : updateUserProfileInProjects.js + * author : Priyanka Pradeep + * created-date : 10-Nov-2022 + * Description : Migration script for update userProfile in project + */ + + const path = require("path"); + let rootPath = path.join(__dirname, '../../') + require('dotenv').config({ path: rootPath+'/.env' }) + + let _ = require("lodash"); + let mongoUrl = process.env.MONGODB_URL; + let dbName = mongoUrl.split("/").pop(); + let url = mongoUrl.split(dbName)[0]; + var MongoClient = require('mongodb').MongoClient; + var ObjectId = require('mongodb').ObjectID; + + var fs = require('fs'); + + +(async () => { + + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + + let updatedProjectIds = []; + let deletedSolutionIds = []; + let deletedProgramIds = []; + + + + //get all projects id where user profile is not there. + let projectDocument = await db.collection('projects').find({ + userRoleInformation: {$exists : false}, + isAPrivateProgram: true, + }).project({_id:1}).toArray(); + + + let chunkOfProjectDocument = _.chunk(projectDocument, 10); + // console.log(chunkOfProjectDocument) + let projectIds; + + for (let pointerToProject = 0; pointerToProject < chunkOfProjectDocument.length; pointerToProject++) { + projectIds = await chunkOfProjectDocument[pointerToProject].map( + projectDoc => { + return projectDoc._id; + } + ); + + + // get project documents from projects collection in Array + let projectDocuments = await db.collection('projects').find({ + _id: { $in :projectIds } + }).project({}).toArray(); + //iterate project documents one by one + for(let counter = 0; counter < projectDocuments.length; counter++) { + + + if(projectDocuments[counter].hasOwnProperty("solutionId")){ + // find solution document form solution collection + let solutionDocument = await db.collection('solutions').find({ + _id: projectDocuments[counter].solutionId + }).project({}).toArray({}) + //find program document form program collection + if(solutionDocument[0].hasOwnProperty("parentSolutionId")){ + + // find parent solution document in same collection + let parentSolutionDocument = await db.collection('solutions').find({ + _id: solutionDocument[0].parentSolutionId}).project({}).toArray({}); + //varibale to update project document + let updateProjectDocument = { + "$set" : {} + }; + updateProjectDocument["$set"]["solutionId"] = parentSolutionDocument[0]._id + updateProjectDocument["$set"]["isAPrivateProgram"] = parentSolutionDocument[0].isAPrivateProgram + updateProjectDocument["$set"]["solutionInformation"] = { + name: parentSolutionDocument[0].name, + description: parentSolutionDocument[0].description, + externalId: parentSolutionDocument[0].externalId, + _id: parentSolutionDocument[0]._id, + } + updateProjectDocument["$set"]["solutionExternalId"] = parentSolutionDocument[0].externalId, + updateProjectDocument["$set"]["programId"] = parentSolutionDocument[0].programId, + updateProjectDocument["$set"]["programExternalId"] = parentSolutionDocument[0].programExternalId + updateProjectDocument["$set"]["programInformation"] = { + _id : parentSolutionDocument[0].programId, + name : parentSolutionDocument[0].programName, + externalId : parentSolutionDocument[0].programExternalId, + description : parentSolutionDocument[0].programDescription, + isAPrivateProgram : parentSolutionDocument[0].isAPrivateProgram + } + if(projectDocument[counter].hasOwnProperty("userProfile")) + { + let userLocations = projectDocuments[counter].userProfile.userLocations + let userRoleInfomration = {} + //get data in userRoleInfomration key + for(let i = 0; i < userLocations.length; i++){ + if(userLocations[i].type !== "school"){ + userRoleInfomration[userLocations[i].type] = userLocations[i].id + }else{ + userRoleInfomration[userLocations[i].type] = userLocations[i].code + } + } + userRoleInfomration.Role = projectDocuments[counter].userProfile.profileUserType.subType ? projectDocuments[counter].userProfile.profileUserType.subType.toUpperCase() : projectDocuments[counter].userProfile.profileUserType.type.toUpperCase() + updateProjectDocument["$set"]["userRoleInformation"] = userRoleInfomration + } + + + //push all updated and deleted id in arrays and save in file + updatedProjectIds.push(projectDocuments[counter]._id) + deletedSolutionIds.push(projectDocuments[counter].solutionId) + deletedProgramIds.push(projectDocuments[counter].programId) + + //update project documents + await db.collection('projects').findOneAndUpdate({ + "_id" : projectDocuments[counter]._id + },updateProjectDocument); + } + } + + + } + + + + + + //write updated project ids to file + fs.writeFile( + 'updatedProjectIds.json', + + JSON.stringify({updatedProjectIds: updatedProjectIds,deletedProgramIds: deletedProgramIds,deletedSolutionIds: deletedSolutionIds}), + + function (err) { + if (err) { + console.error('Crap happens'); + } + } + ); + } + console.log("Updated Project Count : ", updatedProjectIds.length) + console.log("deleted program Count : ", deletedProgramIds.length) + console.log("deleted solutionId Count : ", deletedSolutionIds.length) + console.log("completed") + connection.close(); + } + catch (error) { + console.log(error) + } +})().catch(err => console.error(err)); \ No newline at end of file From 306b44aa9fdb3eae7144580cc0854b083ed49962 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 1 Feb 2023 18:38:07 +0530 Subject: [PATCH 241/373] Added Project Update Script --- .../updatePrivateProgramInProject.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js index b7763913..6003722e 100644 --- a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js +++ b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js @@ -1,8 +1,8 @@ /** - * name : updateUserProfileInProjects.js - * author : Priyanka Pradeep + * name : updatePrivateProgramInProject.js + * author : Ankit Shahu * created-date : 10-Nov-2022 - * Description : Migration script for update userProfile in project + * Description : Migration script for update project */ const path = require("path"); From 85631c99241f0d011f0b6090ef6e7589c4663fa8 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 2 Feb 2023 09:34:01 +0530 Subject: [PATCH 242/373] add delete also --- .../updatePrivateProgramInProject.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js index 6003722e..01fc4d58 100644 --- a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js +++ b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js @@ -58,7 +58,7 @@ for(let counter = 0; counter < projectDocuments.length; counter++) { - if(projectDocuments[counter].hasOwnProperty("solutionId")){ + if(projectDocuments[counter].hasOwnProperty("solutionId") && projectDocuments[counter].isAPrivateProgram){ // find solution document form solution collection let solutionDocument = await db.collection('solutions').find({ _id: projectDocuments[counter].solutionId @@ -119,9 +119,19 @@ },updateProjectDocument); } } - - } + + + await db.collection('solutions').deleteMany({ + _id: { + $in: deletedSolutionIds + } + }) + await db.collection('programs').deleteMany({ + _id: { + $in: deletedProgramIds + } + }) From 19a65074570eb6d06576d6ec1aa0e7be3c743d1a Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 2 Feb 2023 09:38:43 +0530 Subject: [PATCH 243/373] add delete also --- .../updatePrivateProgramInProject.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js index 01fc4d58..76df459a 100644 --- a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js +++ b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js @@ -61,10 +61,12 @@ if(projectDocuments[counter].hasOwnProperty("solutionId") && projectDocuments[counter].isAPrivateProgram){ // find solution document form solution collection let solutionDocument = await db.collection('solutions').find({ - _id: projectDocuments[counter].solutionId + _id: projectDocuments[counter].solutionId, + parentSolutionId : {$exists:true}, + isAPrivateProgram : true }).project({}).toArray({}) //find program document form program collection - if(solutionDocument[0].hasOwnProperty("parentSolutionId")){ + if(solutionDocument.length == 1){ // find parent solution document in same collection let parentSolutionDocument = await db.collection('solutions').find({ From 00fb7086c5786569af7aa0b9240c362509c798ac Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 2 Feb 2023 19:21:38 +0530 Subject: [PATCH 244/373] Added Both Script --- .../deleteAndUpdateAttachmentsInProject.js | 216 ++++++++++++++++++ .../updatePrivateProgramInProject.js | 20 +- 2 files changed, 225 insertions(+), 11 deletions(-) create mode 100644 migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js diff --git a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js new file mode 100644 index 00000000..348b8ece --- /dev/null +++ b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js @@ -0,0 +1,216 @@ +const path = require("path"); +let rootPath = path.join(__dirname, '../../') +require('dotenv').config({ path: rootPath+'/.env' }) + +let _ = require("lodash"); +let mongoUrl = process.env.MONGODB_URL; +let dbName = mongoUrl.split("/").pop(); +let url = mongoUrl.split(dbName)[0]; +var MongoClient = require('mongodb').MongoClient; +var ObjectId = require('mongodb').ObjectID; +var request = require('request'); +var fs = require('fs'); +const { at } = require("lodash"); + +const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; + + +(async () => { + + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + // check project attachments for isUploaded = false data and remove the attachment object + let collectionDocs = await db.collection("projectsss").find({ + "$or": [ + { + "attachments.isUploaded": { + "$exists": true + },"attachments.isUploaded": false + }, + { + "tasks.attachments.isUploaded": { + "$exists": true + },"tasks.attachments.isUploaded": false + } + ] + }).project({_id:1}).toArray(); + + //varibale to store all projectIds which are updated + let projectIds = []; + collectionDocs.forEach( eachDoc => { + projectIds.push(eachDoc._id); + }) + + let chunkOfProjectIds = _.chunk(projectIds, 5); + let UpdatedProjectId = [] + //loop project chunks + for ( let chunkPointer = 0; chunkPointer < chunkOfProjectIds.length; chunkPointer++ ) { + + //chunk of project ids + let projectId = chunkOfProjectIds[chunkPointer]; + + //loop for chunk of project id in chunk + for ( let projectIdpointer = 0 ; projectIdpointer < projectId.length; projectIdpointer++ ) { + let id = projectId[projectIdpointer]; + + //pull project Data from DB + let pullProjectData = await db.collection("projectsss").find({ + _id: id + }).project({}).toArray({}) + + //store in varibale to avoid using [0] + pullProjectData = pullProjectData[0] + + //update Object + let updateObject = { + "$set" : {} + } + + //check if project Document has attachments or not if present then checks length of attachment it should be greater than 0 + if( pullProjectData.hasOwnProperty('attachments') && pullProjectData.attachments.length > 0 ) { + + //varibale to store updated attachment objects + let attachmentsPresent = [] + + //for loop for each attachment + for(let j = 0; j< pullProjectData.attachments.length; j++){ + + //check if isUploaded key is present or not and isUploaded should be false and checks type of attachment + if(pullProjectData.attachments[j].hasOwnProperty("isUploaded") && !pullProjectData.attachments[j].isUploaded && pullProjectData.attachments[j].type !== "link"){ + + //checks if document is present or not + let documentExist = await getDocumentStatus( pullProjectData.attachments[j].sourcePath) + //if present then push object to new array and update isUploaded to true + if(documentExist.success){ + pullProjectData.attachments[j].isUploaded = true + attachmentsPresent.push(pullProjectData.attachments[j]) + } + }else{ + //if isUploaded is not present then push object to new array and if type is link then also + attachmentsPresent.push(pullProjectData.attachments[j]) + } + } + //assign attachmentPresent object to update variable + updateObject['$set']['attachments'] = attachmentsPresent + } + + //check if project has tasks available and length of tasks array should be greater than 0 + if( pullProjectData.hasOwnProperty('tasks') && pullProjectData.tasks.length > 0){ + + + //varibale to store updated task objects + let newTaskWithValidatedAttachments = [] + //for loop for each task + for(let j = 0; j< pullProjectData.tasks.length; j++){ + + //store task object in task + let task = pullProjectData.tasks[j] + + //checks if task object has key attachment present or not + if(task.hasOwnProperty("attachments")){ + + //varible to store attachment object of task + let attachmentsPresent = [] + + + //for loop for each attachment in each task + for(let k = 0; k < task.attachments.length; k++){ + + //check if isUploaded key is present or not and isUploaded should be false and checks type + if(task.attachments[k].hasOwnProperty("isUploaded") && !task.attachments[k].isUploaded && task.attachments[k].type !== "link"){ + + //checks if document is present or not + let documentExist = await getDocumentStatus( task.attachments[k].sourcePath) + //if present then push object to new array and update isUploaded to true + if(documentExist.success){ + task.attachments[k].isUploaded = true + attachmentsPresent.push(task.attachments[k]) + } + }else{ + //if isUploaded is not present then push object to new array and if type is link then also + attachmentsPresent.push(task.attachments[k]) + } + } + //assign attachmentPresent array to task attachments + task.attachments = attachmentsPresent + } + //push task to new array of tasks key + newTaskWithValidatedAttachments.push(task) + } + //assign all valid task to task for update + updateObject['$set']['tasks'] = newTaskWithValidatedAttachments + } + //push project id which is validated + UpdatedProjectId.push(id) + //update project with new varibales + await db.collection("projectsss").updateOne({_id:id},updateObject) + } + + + } + console.log(UpdatedProjectId) + + //function to check if document exists + function getDocumentStatus (sourcePath) { + return new Promise(async (resolve, reject) => { + try { + // <--- Important : This url endpoint is private do not use it for regular workflows ---> + let url = filePathUrl + sourcePath; + const options = { + headers : { + } + }; + request.get(url,options,userReadCallback); + let result = { + success : true + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + // let response = JSON.parse(data.body); + console.log(data.statusCode) + if( data.statusCode === 200 ) { + result.success = true; + } else { + result.success = false; + } + + } + return resolve(result); + } + setTimeout(function () { + return resolve (result = { + success : false + }); + }, 5000); + + } catch (error) { + return reject(error); + } + }) + } + + fs.writeFile( + 'updatedProjectWithAttachments.json', + + JSON.stringify({updatedProjectIds: UpdatedProjectId}), + + function (err) { + if (err) { + console.error('Crap happens'); + } + } + ); + + + console.log("finished project attachment deletion based on isUploaded:= false, completed...") + connection.close(); + } + catch (error) { + console.log(error) + } +})().catch(err => console.error(err)); + + diff --git a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js index 76df459a..d0496beb 100644 --- a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js +++ b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js @@ -119,21 +119,19 @@ await db.collection('projects').findOneAndUpdate({ "_id" : projectDocuments[counter]._id },updateProjectDocument); + + await db.collection('solutions').deleteOne({ + _id: projectDocuments[counter].solutionId + }) + await db.collection('programs').deleteOne({ + _id: projectDocuments[counter].programId + }) } } } - await db.collection('solutions').deleteMany({ - _id: { - $in: deletedSolutionIds - } - }) - await db.collection('programs').deleteMany({ - _id: { - $in: deletedProgramIds - } - }) + @@ -141,7 +139,7 @@ //write updated project ids to file fs.writeFile( - 'updatedProjectIds.json', + 'updatedProjectIdsAll.json', JSON.stringify({updatedProjectIds: updatedProjectIds,deletedProgramIds: deletedProgramIds,deletedSolutionIds: deletedSolutionIds}), From 2ec50de5f621c4407512b3bdbe9d35e7993f1718 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 09:19:06 +0530 Subject: [PATCH 245/373] Added Both Script --- .../deleteAndUpdateAttachmentsInProject.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js index 348b8ece..00ae1b91 100644 --- a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js +++ b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js @@ -21,7 +21,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; let db = connection.db(dbName); try { // check project attachments for isUploaded = false data and remove the attachment object - let collectionDocs = await db.collection("projectsss").find({ + let collectionDocs = await db.collection("projects").find({ "$or": [ { "attachments.isUploaded": { @@ -55,7 +55,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; let id = projectId[projectIdpointer]; //pull project Data from DB - let pullProjectData = await db.collection("projectsss").find({ + let pullProjectData = await db.collection("projects").find({ _id: id }).project({}).toArray({}) @@ -144,7 +144,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; //push project id which is validated UpdatedProjectId.push(id) //update project with new varibales - await db.collection("projectsss").updateOne({_id:id},updateObject) + await db.collection("projects").updateOne({_id:id},updateObject) } From bf2be1b6612ddc9775625f0e8a89d1dcb6485ebb Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 09:19:54 +0530 Subject: [PATCH 246/373] Added Both Script --- .../deleteAndUpdateAttachmentsInProject.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js index 00ae1b91..747d3bac 100644 --- a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js +++ b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js @@ -1,3 +1,10 @@ +/** + * name : updatePrivateProgramInProject.js + * author : Ankit Shahu + * created-date : 10-Nov-2022 + * Description : Migration script for update project + */ + const path = require("path"); let rootPath = path.join(__dirname, '../../') require('dotenv').config({ path: rootPath+'/.env' }) From 27697e6290c3793c4ae97bdf9c554be3c7b0cccf Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 09:20:42 +0530 Subject: [PATCH 247/373] Added Both Script --- .../deleteAndUpdateAttachmentsInProject.js | 2 +- .../privateProgramInProjects/updatePrivateProgramInProject.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js index 747d3bac..e48ec9a8 100644 --- a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js +++ b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js @@ -1,7 +1,7 @@ /** * name : updatePrivateProgramInProject.js * author : Ankit Shahu - * created-date : 10-Nov-2022 + * created-date : 02-Feb-2023 * Description : Migration script for update project */ diff --git a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js index d0496beb..39d3e70f 100644 --- a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js +++ b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js @@ -1,7 +1,7 @@ /** * name : updatePrivateProgramInProject.js * author : Ankit Shahu - * created-date : 10-Nov-2022 + * created-date : 02-Feb-2023 * Description : Migration script for update project */ From 1db856c3666ed5ee0f3e95b896c1b6cd97492e07 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 15:17:39 +0530 Subject: [PATCH 248/373] Updated PR --- .../migratePrivateProjectToPublicProgram.js | 166 +++++++++++++++ .../removeAttachmentsNotUploadedInCloud.js | 200 ++++++++++++++++++ 2 files changed, 366 insertions(+) create mode 100644 migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js create mode 100644 migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js diff --git a/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js b/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js new file mode 100644 index 00000000..50aa2eab --- /dev/null +++ b/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js @@ -0,0 +1,166 @@ +/** + * name : updatePrivateProgramInProject.js + * author : Ankit Shahu + * created-date : 02-Feb-2023 + * Description : Migration script for update project + */ + + const path = require("path"); + let rootPath = path.join(__dirname, '../../') + require('dotenv').config({ path: rootPath+'/.env' }) + + let _ = require("lodash"); + let mongoUrl = process.env.MONGODB_URL; + let dbName = mongoUrl.split("/").pop(); + let url = mongoUrl.split(dbName)[0]; + var MongoClient = require('mongodb').MongoClient; + var ObjectId = require('mongodb').ObjectID; + + var fs = require('fs'); + + +(async () => { + + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + + let updatedProjectIds = []; + let deletedSolutionIds = []; + let deletedProgramIds = []; + + + + //get all projectss id where user profile is not there. + let projectDocument = await db.collection('projectss').find({ + userRoleInformation: {$exists : false}, + isAPrivateProgram: true, + }).project({_id:1,userProfile:1}).toArray(); + + + let chunkOfProjectDocument = _.chunk(projectDocument, 10); + // console.log(chunkOfProjectDocument) + let projectIds; + + for (let pointerToProject = 0; pointerToProject < chunkOfProjectDocument.length; pointerToProject++) { + projectIds = await chunkOfProjectDocument[pointerToProject].map( + projectDoc => { + return projectDoc._id; + } + ); + + + // get project documents from projectss collection in Array + let projectDocuments = await db.collection('projectss').find({ + _id: { $in :projectIds } + }).project({}).toArray(); + //iterate project documents one by one + for(let counter = 0; counter < projectDocuments.length; counter++) { + + + if(projectDocuments[counter].hasOwnProperty("solutionId") && projectDocuments[counter].isAPrivateProgram){ + // find solution document form solution collection + let solutionDocument = await db.collection('solutionss').find({ + _id: projectDocuments[counter].solutionId, + parentSolutionId : {$exists:true}, + isAPrivateProgram : true + }).project({}).toArray({}) + //find program document form program collection + if(solutionDocument.length == 1){ + + // find parent solution document in same collection + let parentSolutionDocument = await db.collection('solutionss').find({ + _id: solutionDocument[0].parentSolutionId}).project({}).toArray({}); + //varibale to update project document + let updateProjectDocument = { + "$set" : {} + }; + updateProjectDocument["$set"]["solutionId"] = parentSolutionDocument[0]._id + updateProjectDocument["$set"]["isAPrivateProgram"] = parentSolutionDocument[0].isAPrivateProgram + updateProjectDocument["$set"]["solutionInformation"] = { + name: parentSolutionDocument[0].name, + description: parentSolutionDocument[0].description, + externalId: parentSolutionDocument[0].externalId, + _id: parentSolutionDocument[0]._id, + } + updateProjectDocument["$set"]["solutionExternalId"] = parentSolutionDocument[0].externalId, + updateProjectDocument["$set"]["programId"] = parentSolutionDocument[0].programId, + updateProjectDocument["$set"]["programExternalId"] = parentSolutionDocument[0].programExternalId + updateProjectDocument["$set"]["programInformation"] = { + _id : parentSolutionDocument[0].programId, + name : parentSolutionDocument[0].programName, + externalId : parentSolutionDocument[0].programExternalId, + description : parentSolutionDocument[0].programDescription, + isAPrivateProgram : parentSolutionDocument[0].isAPrivateProgram + } + if(projectDocument[counter].hasOwnProperty("userProfile")) + { + let userLocations = projectDocuments[counter].userProfile.userLocations + let userRoleInfomration = {} + //get data in userRoleInfomration key + for(let userLocationCounter = 0; userLocationCounter < userLocations.length; userLocationCounter++){ + if(userLocations[userLocationCounter].type !== "school"){ + userRoleInfomration[userLocations[userLocationCounter].type] = userLocations[userLocationCounter].id + }else{ + userRoleInfomration[userLocations[userLocationCounter].type] = userLocations[userLocationCounter].code + } + } + let Roles = "" + for(let roleCounter = 0; roleCounter < projectDocuments[counter].userProfile.profileUserTypes.length; roleCounter++){ + Roles = Roles !== "" ? Roles+"," : Roles + Roles += (projectDocuments[counter].userProfile.profileUserTypes[roleCounter].subType ? projectDocuments[counter].userProfile.profileUserTypes[roleCounter].subType.toUpperCase() : projectDocuments[counter].userProfile.profileUserTypes[roleCounter].type.toUpperCase()) + } + userRoleInfomration.Role = Roles + updateProjectDocument["$set"]["userRoleInformation"] = userRoleInfomration + } + + //push all updated and deleted id in arrays and save in file + updatedProjectIds.push(projectDocuments[counter]._id) + deletedSolutionIds.push(projectDocuments[counter].solutionId) + deletedProgramIds.push(projectDocuments[counter].programId) + + // update project documents + await db.collection('projectss').findOneAndUpdate({ + "_id" : projectDocuments[counter]._id + },updateProjectDocument); + + await db.collection('solutionss').deleteOne({ + _id: projectDocuments[counter].solutionId + }) + await db.collection('programs').deleteOne({ + _id: projectDocuments[counter].programId + }) + } + } + } + + + + + + + + + //write updated project ids to file + fs.writeFile( + 'updatedProjectIdsAll.json', + + JSON.stringify({updatedProjectIds: updatedProjectIds,deletedProgramIds: deletedProgramIds,deletedSolutionIds: deletedSolutionIds}), + + function (err) { + if (err) { + console.error('Crap happens'); + } + } + ); + } + console.log("Updated Project Count : ", updatedProjectIds.length) + console.log("deleted program Count : ", deletedProgramIds.length) + console.log("deleted solutionId Count : ", deletedSolutionIds.length) + console.log("completed") + connection.close(); + } + catch (error) { + console.log(error) + } +})().catch(err => console.error(err)); \ No newline at end of file diff --git a/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js new file mode 100644 index 00000000..6557e485 --- /dev/null +++ b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js @@ -0,0 +1,200 @@ +/** + * name : updatePrivateProgramInProject.js + * author : Ankit Shahu + * created-date : 02-Feb-2023 + * Description : Migration script for update project + */ + +const path = require("path"); +let rootPath = path.join(__dirname, '../../') +require('dotenv').config({ path: rootPath+'/.env' }) + +let _ = require("lodash"); +let mongoUrl = process.env.MONGODB_URL; +let dbName = mongoUrl.split("/").pop(); +let url = mongoUrl.split(dbName)[0]; +var MongoClient = require('mongodb').MongoClient; +var ObjectId = require('mongodb').ObjectID; +var request = require('request'); +var fs = require('fs'); +const { at } = require("lodash"); + +const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; + + +(async () => { + + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + // check project attachments for isUploaded = false data and remove the attachment object + let collectionDocs = await db.collection('projectsss').find({ + "$or": [ + { + "attachments.isUploaded": false + }, + { + "tasks.attachments.isUploaded": false + } + ] + }).project({_id:1}).toArray(); + + //varibale to store all projectIds which are updated + let projectIds = []; + collectionDocs.forEach( eachDoc => { + projectIds.push(eachDoc._id); + }) + + let chunkOfProjectIds = _.chunk(projectIds, 10); + let UpdatedProjectId = [] + //loop project chunks + for ( let chunkPointer = 0; chunkPointer < chunkOfProjectIds.length; chunkPointer++ ) { + + //chunk of project ids + let projectId = chunkOfProjectIds[chunkPointer]; + + //loop for chunk of project id in chunk + for ( let projectIdpointer = 0 ; projectIdpointer < projectId.length; projectIdpointer++ ) { + let id = projectId[projectIdpointer]; + + //pull project Data from DB + let pullProjectData = await db.collection('projectsss').find({ + _id: id + }).project({}).toArray({}) + + //store in varibale to avoid using [0] + pullProjectData = pullProjectData[0] + + //update Object + let updateObject = { + "$set" : {} + } + + //check if project Document has attachments or not if present then checks length of attachment it should be greater than 0 + if( pullProjectData.hasOwnProperty('attachments') && pullProjectData.attachments.length > 0 ) { + + //assign attachmentPresent object to update variable + updateObject['$set']['attachments'] = await validatedAttachments( pullProjectData.attachments) + } + + //check if project has tasks available and length of tasks array should be greater than 0 + if( pullProjectData.hasOwnProperty('tasks') && pullProjectData.tasks.length > 0){ + + + //varibale to store updated task objects + let newTaskWithValidatedAttachments = [] + //for loop for each task + for(let taskCounter = 0; taskCounter< pullProjectData.tasks.length; taskCounter++){ + + //store task object in task + let task = pullProjectData.tasks[taskCounter] + + //checks if task object has key attachment present or not + if(task.hasOwnProperty("attachments")){ + + //assign attachmentPresent array to task attachments + task.attachments = await validatedAttachments(task.attachments) + } + //push task to new array of tasks key + newTaskWithValidatedAttachments.push(task) + } + //assign all valid task to task for update + updateObject['$set']['tasks'] = newTaskWithValidatedAttachments + } + //push project id which is validated + + UpdatedProjectId.push(id) + //update project with new varibales + await db.collection('projectsss').updateOne({_id:id},updateObject) + } + + + } + console.log(UpdatedProjectId) + + async function validatedAttachments(attachments){ + //varibale to store updated attachment objects + let attachmentsPresent = [] + + //for loop for each attachment + for(let attachmentCounter = 0; attachmentCounter< attachments.length; attachmentCounter++){ + + //check if isUploaded key is present or not and isUploaded should be false and checks type of attachment + if(attachments[attachmentCounter].hasOwnProperty("isUploaded") && !attachments[attachmentCounter].isUploaded && attachments[attachmentCounter].type !== "link"){ + + //checks if document is present or not + let documentExist = await getDocumentStatus(attachments[attachmentCounter].sourcePath) + //if present then push object to new array and update isUploaded to true + if(documentExist.success){ + attachments[attachmentCounter].isUploaded = true + attachmentsPresent.push(attachments[attachmentCounter]) + } + }else{ + //if isUploaded is not present then push object to new array and if type is link then also + attachmentsPresent.push(attachments[attachmentCounter]) + } + } + + return attachmentsPresent; + } + + //function to check if document exists + function getDocumentStatus (sourcePath) { + return new Promise(async (resolve, reject) => { + try { + let url = filePathUrl + sourcePath; + const options = { + headers : { + } + }; + request.get(url,options,userReadCallback); + let result = { + success : true + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + if( data.statusCode === 200 ) { + result.success = true; + } else { + result.success = false; + } + + } + return resolve(result); + } + setTimeout(function () { + return resolve (result = { + success : false + }); + }, 5000); + + } catch (error) { + return reject(error); + } + }) + } + + fs.writeFile( + 'updatedProjectWithAttachments.json', + + JSON.stringify({updatedProjectIds: UpdatedProjectId}), + + function (err) { + if (err) { + console.error('Crap happens'); + } + } + ); + + console.log("Updated Projects", UpdatedProjectId.length) + console.log("finished project attachment deletion based on isUploaded:= false, completed...") + connection.close(); + } + catch (error) { + console.log(error) + } +})().catch(err => console.error(err)); + + From 56d73c3cdfb06516ccf0db1f56af036662d865f0 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 15:21:49 +0530 Subject: [PATCH 249/373] Done with Scripts --- .../deleteAndUpdateAttachmentsInProject.js | 223 ------------------ .../updatePrivateProgramInProject.js | 162 ------------- 2 files changed, 385 deletions(-) delete mode 100644 migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js delete mode 100644 migrations/privateProgramInProjects/updatePrivateProgramInProject.js diff --git a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js b/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js deleted file mode 100644 index e48ec9a8..00000000 --- a/migrations/privateProgramInProjects/deleteAndUpdateAttachmentsInProject.js +++ /dev/null @@ -1,223 +0,0 @@ -/** - * name : updatePrivateProgramInProject.js - * author : Ankit Shahu - * created-date : 02-Feb-2023 - * Description : Migration script for update project - */ - -const path = require("path"); -let rootPath = path.join(__dirname, '../../') -require('dotenv').config({ path: rootPath+'/.env' }) - -let _ = require("lodash"); -let mongoUrl = process.env.MONGODB_URL; -let dbName = mongoUrl.split("/").pop(); -let url = mongoUrl.split(dbName)[0]; -var MongoClient = require('mongodb').MongoClient; -var ObjectId = require('mongodb').ObjectID; -var request = require('request'); -var fs = require('fs'); -const { at } = require("lodash"); - -const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; - - -(async () => { - - let connection = await MongoClient.connect(url, { useNewUrlParser: true }); - let db = connection.db(dbName); - try { - // check project attachments for isUploaded = false data and remove the attachment object - let collectionDocs = await db.collection("projects").find({ - "$or": [ - { - "attachments.isUploaded": { - "$exists": true - },"attachments.isUploaded": false - }, - { - "tasks.attachments.isUploaded": { - "$exists": true - },"tasks.attachments.isUploaded": false - } - ] - }).project({_id:1}).toArray(); - - //varibale to store all projectIds which are updated - let projectIds = []; - collectionDocs.forEach( eachDoc => { - projectIds.push(eachDoc._id); - }) - - let chunkOfProjectIds = _.chunk(projectIds, 5); - let UpdatedProjectId = [] - //loop project chunks - for ( let chunkPointer = 0; chunkPointer < chunkOfProjectIds.length; chunkPointer++ ) { - - //chunk of project ids - let projectId = chunkOfProjectIds[chunkPointer]; - - //loop for chunk of project id in chunk - for ( let projectIdpointer = 0 ; projectIdpointer < projectId.length; projectIdpointer++ ) { - let id = projectId[projectIdpointer]; - - //pull project Data from DB - let pullProjectData = await db.collection("projects").find({ - _id: id - }).project({}).toArray({}) - - //store in varibale to avoid using [0] - pullProjectData = pullProjectData[0] - - //update Object - let updateObject = { - "$set" : {} - } - - //check if project Document has attachments or not if present then checks length of attachment it should be greater than 0 - if( pullProjectData.hasOwnProperty('attachments') && pullProjectData.attachments.length > 0 ) { - - //varibale to store updated attachment objects - let attachmentsPresent = [] - - //for loop for each attachment - for(let j = 0; j< pullProjectData.attachments.length; j++){ - - //check if isUploaded key is present or not and isUploaded should be false and checks type of attachment - if(pullProjectData.attachments[j].hasOwnProperty("isUploaded") && !pullProjectData.attachments[j].isUploaded && pullProjectData.attachments[j].type !== "link"){ - - //checks if document is present or not - let documentExist = await getDocumentStatus( pullProjectData.attachments[j].sourcePath) - //if present then push object to new array and update isUploaded to true - if(documentExist.success){ - pullProjectData.attachments[j].isUploaded = true - attachmentsPresent.push(pullProjectData.attachments[j]) - } - }else{ - //if isUploaded is not present then push object to new array and if type is link then also - attachmentsPresent.push(pullProjectData.attachments[j]) - } - } - //assign attachmentPresent object to update variable - updateObject['$set']['attachments'] = attachmentsPresent - } - - //check if project has tasks available and length of tasks array should be greater than 0 - if( pullProjectData.hasOwnProperty('tasks') && pullProjectData.tasks.length > 0){ - - - //varibale to store updated task objects - let newTaskWithValidatedAttachments = [] - //for loop for each task - for(let j = 0; j< pullProjectData.tasks.length; j++){ - - //store task object in task - let task = pullProjectData.tasks[j] - - //checks if task object has key attachment present or not - if(task.hasOwnProperty("attachments")){ - - //varible to store attachment object of task - let attachmentsPresent = [] - - - //for loop for each attachment in each task - for(let k = 0; k < task.attachments.length; k++){ - - //check if isUploaded key is present or not and isUploaded should be false and checks type - if(task.attachments[k].hasOwnProperty("isUploaded") && !task.attachments[k].isUploaded && task.attachments[k].type !== "link"){ - - //checks if document is present or not - let documentExist = await getDocumentStatus( task.attachments[k].sourcePath) - //if present then push object to new array and update isUploaded to true - if(documentExist.success){ - task.attachments[k].isUploaded = true - attachmentsPresent.push(task.attachments[k]) - } - }else{ - //if isUploaded is not present then push object to new array and if type is link then also - attachmentsPresent.push(task.attachments[k]) - } - } - //assign attachmentPresent array to task attachments - task.attachments = attachmentsPresent - } - //push task to new array of tasks key - newTaskWithValidatedAttachments.push(task) - } - //assign all valid task to task for update - updateObject['$set']['tasks'] = newTaskWithValidatedAttachments - } - //push project id which is validated - UpdatedProjectId.push(id) - //update project with new varibales - await db.collection("projects").updateOne({_id:id},updateObject) - } - - - } - console.log(UpdatedProjectId) - - //function to check if document exists - function getDocumentStatus (sourcePath) { - return new Promise(async (resolve, reject) => { - try { - // <--- Important : This url endpoint is private do not use it for regular workflows ---> - let url = filePathUrl + sourcePath; - const options = { - headers : { - } - }; - request.get(url,options,userReadCallback); - let result = { - success : true - }; - function userReadCallback(err, data) { - if (err) { - result.success = false; - } else { - // let response = JSON.parse(data.body); - console.log(data.statusCode) - if( data.statusCode === 200 ) { - result.success = true; - } else { - result.success = false; - } - - } - return resolve(result); - } - setTimeout(function () { - return resolve (result = { - success : false - }); - }, 5000); - - } catch (error) { - return reject(error); - } - }) - } - - fs.writeFile( - 'updatedProjectWithAttachments.json', - - JSON.stringify({updatedProjectIds: UpdatedProjectId}), - - function (err) { - if (err) { - console.error('Crap happens'); - } - } - ); - - - console.log("finished project attachment deletion based on isUploaded:= false, completed...") - connection.close(); - } - catch (error) { - console.log(error) - } -})().catch(err => console.error(err)); - - diff --git a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js b/migrations/privateProgramInProjects/updatePrivateProgramInProject.js deleted file mode 100644 index 39d3e70f..00000000 --- a/migrations/privateProgramInProjects/updatePrivateProgramInProject.js +++ /dev/null @@ -1,162 +0,0 @@ -/** - * name : updatePrivateProgramInProject.js - * author : Ankit Shahu - * created-date : 02-Feb-2023 - * Description : Migration script for update project - */ - - const path = require("path"); - let rootPath = path.join(__dirname, '../../') - require('dotenv').config({ path: rootPath+'/.env' }) - - let _ = require("lodash"); - let mongoUrl = process.env.MONGODB_URL; - let dbName = mongoUrl.split("/").pop(); - let url = mongoUrl.split(dbName)[0]; - var MongoClient = require('mongodb').MongoClient; - var ObjectId = require('mongodb').ObjectID; - - var fs = require('fs'); - - -(async () => { - - let connection = await MongoClient.connect(url, { useNewUrlParser: true }); - let db = connection.db(dbName); - try { - - let updatedProjectIds = []; - let deletedSolutionIds = []; - let deletedProgramIds = []; - - - - //get all projects id where user profile is not there. - let projectDocument = await db.collection('projects').find({ - userRoleInformation: {$exists : false}, - isAPrivateProgram: true, - }).project({_id:1}).toArray(); - - - let chunkOfProjectDocument = _.chunk(projectDocument, 10); - // console.log(chunkOfProjectDocument) - let projectIds; - - for (let pointerToProject = 0; pointerToProject < chunkOfProjectDocument.length; pointerToProject++) { - projectIds = await chunkOfProjectDocument[pointerToProject].map( - projectDoc => { - return projectDoc._id; - } - ); - - - // get project documents from projects collection in Array - let projectDocuments = await db.collection('projects').find({ - _id: { $in :projectIds } - }).project({}).toArray(); - //iterate project documents one by one - for(let counter = 0; counter < projectDocuments.length; counter++) { - - - if(projectDocuments[counter].hasOwnProperty("solutionId") && projectDocuments[counter].isAPrivateProgram){ - // find solution document form solution collection - let solutionDocument = await db.collection('solutions').find({ - _id: projectDocuments[counter].solutionId, - parentSolutionId : {$exists:true}, - isAPrivateProgram : true - }).project({}).toArray({}) - //find program document form program collection - if(solutionDocument.length == 1){ - - // find parent solution document in same collection - let parentSolutionDocument = await db.collection('solutions').find({ - _id: solutionDocument[0].parentSolutionId}).project({}).toArray({}); - //varibale to update project document - let updateProjectDocument = { - "$set" : {} - }; - updateProjectDocument["$set"]["solutionId"] = parentSolutionDocument[0]._id - updateProjectDocument["$set"]["isAPrivateProgram"] = parentSolutionDocument[0].isAPrivateProgram - updateProjectDocument["$set"]["solutionInformation"] = { - name: parentSolutionDocument[0].name, - description: parentSolutionDocument[0].description, - externalId: parentSolutionDocument[0].externalId, - _id: parentSolutionDocument[0]._id, - } - updateProjectDocument["$set"]["solutionExternalId"] = parentSolutionDocument[0].externalId, - updateProjectDocument["$set"]["programId"] = parentSolutionDocument[0].programId, - updateProjectDocument["$set"]["programExternalId"] = parentSolutionDocument[0].programExternalId - updateProjectDocument["$set"]["programInformation"] = { - _id : parentSolutionDocument[0].programId, - name : parentSolutionDocument[0].programName, - externalId : parentSolutionDocument[0].programExternalId, - description : parentSolutionDocument[0].programDescription, - isAPrivateProgram : parentSolutionDocument[0].isAPrivateProgram - } - if(projectDocument[counter].hasOwnProperty("userProfile")) - { - let userLocations = projectDocuments[counter].userProfile.userLocations - let userRoleInfomration = {} - //get data in userRoleInfomration key - for(let i = 0; i < userLocations.length; i++){ - if(userLocations[i].type !== "school"){ - userRoleInfomration[userLocations[i].type] = userLocations[i].id - }else{ - userRoleInfomration[userLocations[i].type] = userLocations[i].code - } - } - userRoleInfomration.Role = projectDocuments[counter].userProfile.profileUserType.subType ? projectDocuments[counter].userProfile.profileUserType.subType.toUpperCase() : projectDocuments[counter].userProfile.profileUserType.type.toUpperCase() - updateProjectDocument["$set"]["userRoleInformation"] = userRoleInfomration - } - - - //push all updated and deleted id in arrays and save in file - updatedProjectIds.push(projectDocuments[counter]._id) - deletedSolutionIds.push(projectDocuments[counter].solutionId) - deletedProgramIds.push(projectDocuments[counter].programId) - - //update project documents - await db.collection('projects').findOneAndUpdate({ - "_id" : projectDocuments[counter]._id - },updateProjectDocument); - - await db.collection('solutions').deleteOne({ - _id: projectDocuments[counter].solutionId - }) - await db.collection('programs').deleteOne({ - _id: projectDocuments[counter].programId - }) - } - } - } - - - - - - - - - //write updated project ids to file - fs.writeFile( - 'updatedProjectIdsAll.json', - - JSON.stringify({updatedProjectIds: updatedProjectIds,deletedProgramIds: deletedProgramIds,deletedSolutionIds: deletedSolutionIds}), - - function (err) { - if (err) { - console.error('Crap happens'); - } - } - ); - } - console.log("Updated Project Count : ", updatedProjectIds.length) - console.log("deleted program Count : ", deletedProgramIds.length) - console.log("deleted solutionId Count : ", deletedSolutionIds.length) - console.log("completed") - connection.close(); - } - catch (error) { - console.log(error) - } -})().catch(err => console.error(err)); \ No newline at end of file From 5af2f00ce707b852b7a008261a79f7bd5a8aa6a9 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 15:24:04 +0530 Subject: [PATCH 250/373] Done with Scripts --- .../migratePrivateProjectToPublicProgram.js | 12 ++++++------ .../removeAttachmentsNotUploadedInCloud.js | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js b/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js index 50aa2eab..632be931 100644 --- a/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js +++ b/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js @@ -32,7 +32,7 @@ //get all projectss id where user profile is not there. - let projectDocument = await db.collection('projectss').find({ + let projectDocument = await db.collection('projects').find({ userRoleInformation: {$exists : false}, isAPrivateProgram: true, }).project({_id:1,userProfile:1}).toArray(); @@ -51,7 +51,7 @@ // get project documents from projectss collection in Array - let projectDocuments = await db.collection('projectss').find({ + let projectDocuments = await db.collection('projects').find({ _id: { $in :projectIds } }).project({}).toArray(); //iterate project documents one by one @@ -60,7 +60,7 @@ if(projectDocuments[counter].hasOwnProperty("solutionId") && projectDocuments[counter].isAPrivateProgram){ // find solution document form solution collection - let solutionDocument = await db.collection('solutionss').find({ + let solutionDocument = await db.collection('solutions').find({ _id: projectDocuments[counter].solutionId, parentSolutionId : {$exists:true}, isAPrivateProgram : true @@ -69,7 +69,7 @@ if(solutionDocument.length == 1){ // find parent solution document in same collection - let parentSolutionDocument = await db.collection('solutionss').find({ + let parentSolutionDocument = await db.collection('solutions').find({ _id: solutionDocument[0].parentSolutionId}).project({}).toArray({}); //varibale to update project document let updateProjectDocument = { @@ -120,11 +120,11 @@ deletedProgramIds.push(projectDocuments[counter].programId) // update project documents - await db.collection('projectss').findOneAndUpdate({ + await db.collection('projects').findOneAndUpdate({ "_id" : projectDocuments[counter]._id },updateProjectDocument); - await db.collection('solutionss').deleteOne({ + await db.collection('solutions').deleteOne({ _id: projectDocuments[counter].solutionId }) await db.collection('programs').deleteOne({ diff --git a/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js index 6557e485..e94f429f 100644 --- a/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js +++ b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js @@ -28,7 +28,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; let db = connection.db(dbName); try { // check project attachments for isUploaded = false data and remove the attachment object - let collectionDocs = await db.collection('projectsss').find({ + let collectionDocs = await db.collection('projects').find({ "$or": [ { "attachments.isUploaded": false @@ -58,7 +58,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; let id = projectId[projectIdpointer]; //pull project Data from DB - let pullProjectData = await db.collection('projectsss').find({ + let pullProjectData = await db.collection('projects').find({ _id: id }).project({}).toArray({}) @@ -105,7 +105,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; UpdatedProjectId.push(id) //update project with new varibales - await db.collection('projectsss').updateOne({_id:id},updateObject) + await db.collection('projects').updateOne({_id:id},updateObject) } From da2a6025157a5becaf254435315a48e8e85487d8 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 21:41:20 +0530 Subject: [PATCH 251/373] Updated Code --- .../removeAttachmentsNotUploadedInCloud.js | 93 +++++++++++-------- .../updatedProjectWithAttachments.json | 1 + 2 files changed, 53 insertions(+), 41 deletions(-) create mode 100644 migrations/updateProjectDocuments/updatedProjectWithAttachments.json diff --git a/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js index e94f429f..a29b551a 100644 --- a/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js +++ b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js @@ -4,7 +4,7 @@ * created-date : 02-Feb-2023 * Description : Migration script for update project */ - + "use strict"; const path = require("path"); let rootPath = path.join(__dirname, '../../') require('dotenv').config({ path: rootPath+'/.env' }) @@ -58,12 +58,15 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; let id = projectId[projectIdpointer]; //pull project Data from DB - let pullProjectData = await db.collection('projects').find({ + let pullProjectDataDB = await db.collection('projects').find({ _id: id }).project({}).toArray({}) //store in varibale to avoid using [0] - pullProjectData = pullProjectData[0] + const pullProjectData = pullProjectDataDB[0] + + const allTasksBeforeValidation = JSON.stringify(pullProjectData.tasks) + let allAttachmentsBeforeValidation = "" //update Object let updateObject = { @@ -72,56 +75,74 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; //check if project Document has attachments or not if present then checks length of attachment it should be greater than 0 if( pullProjectData.hasOwnProperty('attachments') && pullProjectData.attachments.length > 0 ) { - + allAttachmentsBeforeValidation = JSON.stringify(pullProjectData.attachments) //assign attachmentPresent object to update variable - updateObject['$set']['attachments'] = await validatedAttachments( pullProjectData.attachments) + updateObject['$set']['attachments'] = await validatedAttachments(pullProjectData.attachments) } //check if project has tasks available and length of tasks array should be greater than 0 if( pullProjectData.hasOwnProperty('tasks') && pullProjectData.tasks.length > 0){ - - //varibale to store updated task objects - let newTaskWithValidatedAttachments = [] + let tasks = pullProjectData.tasks + updateObject['$set']['tasks'] = [...tasks] + //for loop for each task - for(let taskCounter = 0; taskCounter< pullProjectData.tasks.length; taskCounter++){ - - //store task object in task - let task = pullProjectData.tasks[taskCounter] + for(let taskCounter = 0; taskCounter< tasks.length; taskCounter++){ //checks if task object has key attachment present or not - if(task.hasOwnProperty("attachments")){ - + if(tasks[taskCounter].hasOwnProperty("attachments") && tasks[taskCounter].attachments.length>0){ //assign attachmentPresent array to task attachments - task.attachments = await validatedAttachments(task.attachments) + updateObject['$set']['tasks'][taskCounter].attachments = await validatedAttachments((updateObject['$set']['tasks'][taskCounter].attachments)) } - //push task to new array of tasks key - newTaskWithValidatedAttachments.push(task) } - //assign all valid task to task for update - updateObject['$set']['tasks'] = newTaskWithValidatedAttachments } + //push project id which is validated - - UpdatedProjectId.push(id) - //update project with new varibales - await db.collection('projects').updateOne({_id:id},updateObject) + if(JSON.stringify(updateObject["$set"]["tasks"]) != allTasksBeforeValidation || JSON.stringify(updateObject["$set"]["attachments"]) != allAttachmentsBeforeValidation){ + + if(JSON.stringify(updateObject["$set"]["tasks"]) == allTasksBeforeValidation){ + delete updateObject["$set"].tasks + } + if(JSON.stringify(updateObject["$set"]["attachments"]) == allAttachmentsBeforeValidation){ + delete updateObject["$set"].attachments + } + if(updateObject["$set"].hasOwnProperty("attachments") || updateObject["$set"].hasOwnProperty("tasks")){ + UpdatedProjectId.push(id) + //update project with new varibales + await db.collection('projects').updateOne({_id:id},updateObject)} + } } } console.log(UpdatedProjectId) + + + fs.writeFile( + 'updatedProjectWithAttachments.json', + + JSON.stringify({updatedProjectIds: UpdatedProjectId}), + + function (err) { + if (err) { + console.error('Crap happens'); + } + } + ); + + + async function validatedAttachments(attachments){ //varibale to store updated attachment objects let attachmentsPresent = [] - + //for loop for each attachment - for(let attachmentCounter = 0; attachmentCounter< attachments.length; attachmentCounter++){ - + for(let attachmentCounter = 0; attachmentCounter < attachments.length; attachmentCounter++){ + //check if isUploaded key is present or not and isUploaded should be false and checks type of attachment if(attachments[attachmentCounter].hasOwnProperty("isUploaded") && !attachments[attachmentCounter].isUploaded && attachments[attachmentCounter].type !== "link"){ - + //checks if document is present or not let documentExist = await getDocumentStatus(attachments[attachmentCounter].sourcePath) //if present then push object to new array and update isUploaded to true @@ -134,10 +155,10 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; attachmentsPresent.push(attachments[attachmentCounter]) } } - + return attachmentsPresent; } - + //function to check if document exists function getDocumentStatus (sourcePath) { return new Promise(async (resolve, reject) => { @@ -155,6 +176,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; if (err) { result.success = false; } else { + console.log(data.statusCode) if( data.statusCode === 200 ) { result.success = true; } else { @@ -175,18 +197,7 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; } }) } - - fs.writeFile( - 'updatedProjectWithAttachments.json', - - JSON.stringify({updatedProjectIds: UpdatedProjectId}), - - function (err) { - if (err) { - console.error('Crap happens'); - } - } - ); + console.log("Updated Projects", UpdatedProjectId.length) console.log("finished project attachment deletion based on isUploaded:= false, completed...") diff --git a/migrations/updateProjectDocuments/updatedProjectWithAttachments.json b/migrations/updateProjectDocuments/updatedProjectWithAttachments.json new file mode 100644 index 00000000..be932289 --- /dev/null +++ b/migrations/updateProjectDocuments/updatedProjectWithAttachments.json @@ -0,0 +1 @@ +{"updatedProjectIds":[]} \ No newline at end of file From 01260a7c8c79e70671078f468fd2a433e2f4b479 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 3 Feb 2023 21:42:11 +0530 Subject: [PATCH 252/373] Updated Code --- .../updateProjectDocuments/updatedProjectWithAttachments.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 migrations/updateProjectDocuments/updatedProjectWithAttachments.json diff --git a/migrations/updateProjectDocuments/updatedProjectWithAttachments.json b/migrations/updateProjectDocuments/updatedProjectWithAttachments.json deleted file mode 100644 index be932289..00000000 --- a/migrations/updateProjectDocuments/updatedProjectWithAttachments.json +++ /dev/null @@ -1 +0,0 @@ -{"updatedProjectIds":[]} \ No newline at end of file From f4d10e9357de0d57def02eee66ff600fe00c5d92 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 6 Feb 2023 11:24:50 +0530 Subject: [PATCH 253/373] updated script --- .../migratePrivateProjectToPublicProgram.js | 6 +++--- .../removeAttachmentsNotUploadedInCloud.js | 1 - migrations/updateProjectDocuments/updatedProjectIdsAll.json | 1 + .../updatedProjectWithAttachments.json | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 migrations/updateProjectDocuments/updatedProjectIdsAll.json create mode 100644 migrations/updateProjectDocuments/updatedProjectWithAttachments.json diff --git a/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js b/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js index 632be931..1a5866df 100644 --- a/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js +++ b/migrations/updateProjectDocuments/migratePrivateProjectToPublicProgram.js @@ -53,11 +53,11 @@ // get project documents from projectss collection in Array let projectDocuments = await db.collection('projects').find({ _id: { $in :projectIds } - }).project({}).toArray(); + }).project({_id:1,userProfile:1}).toArray(); //iterate project documents one by one for(let counter = 0; counter < projectDocuments.length; counter++) { - + if(projectDocuments[counter].hasOwnProperty("solutionId") && projectDocuments[counter].isAPrivateProgram){ // find solution document form solution collection let solutionDocument = await db.collection('solutions').find({ @@ -93,7 +93,7 @@ description : parentSolutionDocument[0].programDescription, isAPrivateProgram : parentSolutionDocument[0].isAPrivateProgram } - if(projectDocument[counter].hasOwnProperty("userProfile")) + if(projectDocuments[counter].hasOwnProperty("userProfile")) { let userLocations = projectDocuments[counter].userProfile.userLocations let userRoleInfomration = {} diff --git a/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js index a29b551a..b0c29f74 100644 --- a/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js +++ b/migrations/updateProjectDocuments/removeAttachmentsNotUploadedInCloud.js @@ -176,7 +176,6 @@ const filePathUrl = "https://samikshaprod.blob.core.windows.net/samiksha/"; if (err) { result.success = false; } else { - console.log(data.statusCode) if( data.statusCode === 200 ) { result.success = true; } else { diff --git a/migrations/updateProjectDocuments/updatedProjectIdsAll.json b/migrations/updateProjectDocuments/updatedProjectIdsAll.json new file mode 100644 index 00000000..cd5e7369 --- /dev/null +++ b/migrations/updateProjectDocuments/updatedProjectIdsAll.json @@ -0,0 +1 @@ +{"updatedProjectIds":[],"deletedProgramIds":[],"deletedSolutionIds":[]} \ No newline at end of file diff --git a/migrations/updateProjectDocuments/updatedProjectWithAttachments.json b/migrations/updateProjectDocuments/updatedProjectWithAttachments.json new file mode 100644 index 00000000..be932289 --- /dev/null +++ b/migrations/updateProjectDocuments/updatedProjectWithAttachments.json @@ -0,0 +1 @@ +{"updatedProjectIds":[]} \ No newline at end of file From 36d84c6a3992f3b058f5882a6dbd6d702ecdb90f Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 6 Feb 2023 11:25:15 +0530 Subject: [PATCH 254/373] Updated script --- migrations/updateProjectDocuments/updatedProjectIdsAll.json | 1 - .../updateProjectDocuments/updatedProjectWithAttachments.json | 1 - 2 files changed, 2 deletions(-) delete mode 100644 migrations/updateProjectDocuments/updatedProjectIdsAll.json delete mode 100644 migrations/updateProjectDocuments/updatedProjectWithAttachments.json diff --git a/migrations/updateProjectDocuments/updatedProjectIdsAll.json b/migrations/updateProjectDocuments/updatedProjectIdsAll.json deleted file mode 100644 index cd5e7369..00000000 --- a/migrations/updateProjectDocuments/updatedProjectIdsAll.json +++ /dev/null @@ -1 +0,0 @@ -{"updatedProjectIds":[],"deletedProgramIds":[],"deletedSolutionIds":[]} \ No newline at end of file diff --git a/migrations/updateProjectDocuments/updatedProjectWithAttachments.json b/migrations/updateProjectDocuments/updatedProjectWithAttachments.json deleted file mode 100644 index be932289..00000000 --- a/migrations/updateProjectDocuments/updatedProjectWithAttachments.json +++ /dev/null @@ -1 +0,0 @@ -{"updatedProjectIds":[]} \ No newline at end of file From fbcfb11b941f9af5b52b0dd88e7b4c017a7651bc Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Feb 2023 09:05:56 +0530 Subject: [PATCH 255/373] Saving Changes --- databaseQueries/programUsers.js | 22 +++++++++++++++++++ ...Rxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 +++ module/userProjects/helper.js | 4 +++- package.json | 2 +- 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/databaseQueries/programUsers.js b/databaseQueries/programUsers.js index 2a8de03f..451be006 100644 --- a/databaseQueries/programUsers.js +++ b/databaseQueries/programUsers.js @@ -20,4 +20,26 @@ module.exports= class Programs{ } }); } + + + static findProgramIds(userId) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = { + userId: userId + } + + + let programJoinedData = + await database.models.programUsers.find( + queryObject, + {"programId":1} + ).lean(); + return resolve(programJoinedData); + + } catch (error) { + return reject(error); + } + }); +} } \ No newline at end of file diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA new file mode 100644 index 00000000..44c17f6c --- /dev/null +++ b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB +-----END PUBLIC KEY----- diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 13d57e28..86f7651a 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1124,7 +1124,7 @@ module.exports = class UserProjectsHelper { programJoinBody.isResource = true; let joinProgramData = await coreService.programJoin ( solutionDetails.programId, - programJoinData, + programJoinBody, req.userDetails.userToken ); @@ -1975,6 +1975,8 @@ module.exports = class UserProjectsHelper { let totalCount = 0; let data = []; + + let programJoined = await programUsers.findProgramJoined(userId) if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { diff --git a/package.json b/package.json index ab919560..875b6517 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "cli-table": "^0.3.1", "cors": "^2.8.5", "csvtojson": "^2.0.10", - "dotenv": "^8.2.0", + "dotenv": "^8.6.0", "express": "^4.17.1", "express-fileupload": "^1.1.6", "express-validator": "^5.3.1", From 6416529870eb6c09c693f30bad97c175c3365006 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Feb 2023 12:00:57 +0530 Subject: [PATCH 256/373] saving changes --- module/userProjects/helper.js | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 86f7651a..ba2a7685 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1116,25 +1116,25 @@ module.exports = class UserProjectsHelper { } // program join API call let programJoined = await programUsers.findProgramJoined(solutionDetails.programId,userId) - + console.log(programJoined) if(programJoined.length == 0){ - if ( appVersion !== "" && appVersion < 5.2 ) { - let programJoinBody = {}; - programJoinBody.userRoleInformation = req.body.userRoleInformation; - programJoinBody.isResource = true; - let joinProgramData = await coreService.programJoin ( - solutionDetails.programId, - programJoinBody, - req.userDetails.userToken - ); - - if ( !joinProgramData.success ) { - return resolve({ - status: httpStatusCode.bad_request.status, - message: messageConstants.apiResponses.PROGRAM_JOIN_FAILED - }); - } + + let programJoinBody = {}; + programJoinBody.userRoleInformation = bodyData; + programJoinBody.isResource = true; + let joinProgramData = await coreService.programJoin ( + solutionDetails.programId, + programJoinBody, + userToken + ); + + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); } + } let projectCreation = @@ -1976,7 +1976,7 @@ module.exports = class UserProjectsHelper { let totalCount = 0; let data = []; - let programJoined = await programUsers.findProgramJoined(userId) + // let programJoined = await programUsers.findProgramJoined(userId) if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { From f18868829fd9d1ca47086d2b3a1542522a3761bc Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 13 Feb 2023 08:38:51 +0530 Subject: [PATCH 257/373] Raising Pr for project join programs --- generics/services/core.js | 1 + module/project/templates/helper.js | 12 ++ module/userProjects/helper.js | 187 +++++++++++++++++------------ 3 files changed, 120 insertions(+), 80 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index 9fe6d6a3..96e07492 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -761,6 +761,7 @@ const programJoin = function (programId,bodyData,userToken) { } else { let response = data.body; + console.log(response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 6e3404f8..3fce4fd4 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1079,6 +1079,18 @@ module.exports = class ProjectTemplatesHelper { userId : userId, projectTemplateId : templateData[0]._id },["_id"]); + + //check for program enrollment if enrolled then add programJoined true + let programJoined = await programUsers.findProgramIds(userId) + let projects = project.map((e,i)=>{ + let temp = programJoined.find((element)=> { + return element.programId.toString() == e._id.toString() + }) + if(temp.programId) { + templateData[0].programJoined = true; + } + return e; + }) if(project && project.length > 0){ templateData[0].projectId = project[0]._id; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index ba2a7685..c1ac6bf5 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1127,7 +1127,6 @@ module.exports = class UserProjectsHelper { programJoinBody, userToken ); - if ( !joinProgramData.success ) { return resolve({ status: HTTP_STATUS_CODE.bad_request.status, @@ -1229,88 +1228,88 @@ module.exports = class UserProjectsHelper { projectCreation.data["userRole"] = bodyData.role; } - if( - solutionDetails.entityType && bodyData[solutionDetails.entityType] - ) { - let entityInformation = - await surveyService.listEntitiesByLocationIds( - userToken, - [bodyData[solutionDetails.entityType]] - ); - - if( !entityInformation.success ) { - return resolve(entityInformation); - } - - let entityDetails = await _entitiesMetaInformation( - entityInformation.data - ); - - if ( entityDetails && entityDetails.length > 0 ) { - projectCreation.data["entityInformation"] = entityDetails[0]; - } + // if( + // solutionDetails.entityType && bodyData[solutionDetails.entityType] + // ) { + // let entityInformation = + // await surveyService.listEntitiesByLocationIds( + // userToken, + // [bodyData[solutionDetails.entityType]] + // ); + + // if( !entityInformation.success ) { + // return resolve(entityInformation); + // } + + // let entityDetails = await _entitiesMetaInformation( + // entityInformation.data + // ); + + // if ( entityDetails && entityDetails.length > 0 ) { + // projectCreation.data["entityInformation"] = entityDetails[0]; + // } - projectCreation.data.entityId = entityInformation.data[0]._id; - } + // projectCreation.data.entityId = entityInformation.data[0]._id; + // } } projectCreation.data.status = CONSTANTS.common.STARTED; projectCreation.data.lastDownloadedAt = new Date(); - // fetch userRoleInformation from observation if referenecFrom is observation - let addReportInfoToSolution = false; - if ( getUserProfileFromObservation ){ - - let observationDetails = await surveyService.observationDetails( - userToken, - bodyData.submissions.observationId - ); - - if( observationDetails.data && - Object.keys(observationDetails.data).length > 0 && - observationDetails.data.userRoleInformation && - Object.keys(observationDetails.data.userRoleInformation).length > 0 - ) { - - userRoleInformation = observationDetails.data.userRoleInformation; + // // fetch userRoleInformation from observation if referenecFrom is observation + // let addReportInfoToSolution = false; + // if ( getUserProfileFromObservation ){ + + // let observationDetails = await surveyService.observationDetails( + // userToken, + // bodyData.submissions.observationId + // ); + + // if( observationDetails.data && + // Object.keys(observationDetails.data).length > 0 && + // observationDetails.data.userRoleInformation && + // Object.keys(observationDetails.data.userRoleInformation).length > 0 + // ) { + + // userRoleInformation = observationDetails.data.userRoleInformation; - } + // } - if( observationDetails.data && - Object.keys(observationDetails.data).length > 0 && - observationDetails.data.userProfile && - Object.keys(observationDetails.data.userProfile).length > 0 - ) { + // if( observationDetails.data && + // Object.keys(observationDetails.data).length > 0 && + // observationDetails.data.userProfile && + // Object.keys(observationDetails.data.userProfile).length > 0 + // ) { - projectCreation.data.userProfile = observationDetails.data.userProfile; - addReportInfoToSolution = true; + // projectCreation.data.userProfile = observationDetails.data.userProfile; + // addReportInfoToSolution = true; - } else { - //Fetch user profile information by calling sunbird's user read api. - - let userProfile = await userProfileService.profile(userToken, userId); - if ( userProfile.success && - userProfile.data && - userProfile.data.response - ) { - projectCreation.data.userProfile = userProfile.data.response; - addReportInfoToSolution = true; - } - } - - } else { - //Fetch user profile information by calling sunbird's user read api. - - let userProfileData = await userProfileService.profile(userToken, userId); - if ( userProfileData.success && - userProfileData.data && - userProfileData.data.response - ) { - projectCreation.data.userProfile = userProfileData.data.response; - addReportInfoToSolution = true; - } - } + // } else { + // //Fetch user profile information by calling sunbird's user read api. + + // let userProfile = await userProfileService.profile(userToken, userId); + // if ( userProfile.success && + // userProfile.data && + // userProfile.data.response + // ) { + // projectCreation.data.userProfile = userProfile.data.response; + // addReportInfoToSolution = true; + // } + // } + + // } else { + // //Fetch user profile information by calling sunbird's user read api. + + // let userProfileData = await userProfileService.profile(userToken, userId); + // if ( userProfileData.success && + // userProfileData.data && + // userProfileData.data.response + // ) { + // projectCreation.data.userProfile = userProfileData.data.response; + // addReportInfoToSolution = true; + // } + // } projectCreation.data.userRoleInformation = userRoleInformation; @@ -1328,12 +1327,12 @@ module.exports = class UserProjectsHelper { let project = await projectQueries.createProject(projectCreation.data); - if ( addReportInfoToSolution && project.solutionId ) { - let updateSolution = await solutionsHelper.addReportInformationInSolution( - project.solutionId, - project.userProfile - ); - } + // if ( addReportInfoToSolution && project.solutionId ) { + // let updateSolution = await solutionsHelper.addReportInformationInSolution( + // project.solutionId, + // project.userProfile + // ); + // } await kafkaProducersHelper.pushProjectToKafka(project); @@ -1976,8 +1975,16 @@ module.exports = class UserProjectsHelper { let totalCount = 0; let data = []; - // let programJoined = await programUsers.findProgramJoined(userId) - + let programJoined = await programUsers.findProgramIds(userId) + projects.data.data = projects.data.data.map((e,i)=>{ + let temp = programJoined.find((element)=> { + return element.programId.toString() == e.programId.toString() + }) + if(temp.programId) { + e.programJoined = true; + } + return e; + }) if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { totalCount = projects.data.count; @@ -2291,6 +2298,26 @@ module.exports = class UserProjectsHelper { programAndSolutionInformation.data ) } + + let programJoined = await programUsers.findProgramJoined(requestedData.programId,userId) + if(programJoined.length == 0){ + + let programJoinBody = {}; + programJoinBody.isResource = true; + let joinProgramData = await coreService.programJoin ( + solutionDetails.programId, + programJoinBody, + userToken + ); + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); + } + + } + // <- Add certificate template data if ( libraryProjects.data.certificateTemplateId && From 1f63f41b8738ddf4274357ba4930cb5efc66d2fa Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 13 Feb 2023 08:48:12 +0530 Subject: [PATCH 258/373] Done with Project code --- generics/services/core.js | 1 - ...Rxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 - module/project/templates/helper.js | 4 +- module/userProjects/helper.js | 158 +++++++++--------- 4 files changed, 81 insertions(+), 85 deletions(-) delete mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/generics/services/core.js b/generics/services/core.js index 96e07492..9fe6d6a3 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -761,7 +761,6 @@ const programJoin = function (programId,bodyData,userToken) { } else { let response = data.body; - console.log(response); if( response.status === HTTP_STATUS_CODE['ok'].status ) { result["data"] = response.result; } else { diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA deleted file mode 100644 index 44c17f6c..00000000 --- a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB ------END PUBLIC KEY----- diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 3fce4fd4..41f84739 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1083,10 +1083,10 @@ module.exports = class ProjectTemplatesHelper { //check for program enrollment if enrolled then add programJoined true let programJoined = await programUsers.findProgramIds(userId) let projects = project.map((e,i)=>{ - let temp = programJoined.find((element)=> { + let programIds = programJoined.find((element)=> { return element.programId.toString() == e._id.toString() }) - if(temp.programId) { + if(programIds.programId) { templateData[0].programJoined = true; } return e; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c1ac6bf5..9ae3468b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1228,88 +1228,88 @@ module.exports = class UserProjectsHelper { projectCreation.data["userRole"] = bodyData.role; } - // if( - // solutionDetails.entityType && bodyData[solutionDetails.entityType] - // ) { - // let entityInformation = - // await surveyService.listEntitiesByLocationIds( - // userToken, - // [bodyData[solutionDetails.entityType]] - // ); - - // if( !entityInformation.success ) { - // return resolve(entityInformation); - // } - - // let entityDetails = await _entitiesMetaInformation( - // entityInformation.data - // ); - - // if ( entityDetails && entityDetails.length > 0 ) { - // projectCreation.data["entityInformation"] = entityDetails[0]; - // } + if( + solutionDetails.entityType && bodyData[solutionDetails.entityType] + ) { + let entityInformation = + await surveyService.listEntitiesByLocationIds( + userToken, + [bodyData[solutionDetails.entityType]] + ); + + if( !entityInformation.success ) { + return resolve(entityInformation); + } + + let entityDetails = await _entitiesMetaInformation( + entityInformation.data + ); + + if ( entityDetails && entityDetails.length > 0 ) { + projectCreation.data["entityInformation"] = entityDetails[0]; + } - // projectCreation.data.entityId = entityInformation.data[0]._id; - // } + projectCreation.data.entityId = entityInformation.data[0]._id; + } } projectCreation.data.status = CONSTANTS.common.STARTED; projectCreation.data.lastDownloadedAt = new Date(); - // // fetch userRoleInformation from observation if referenecFrom is observation - // let addReportInfoToSolution = false; - // if ( getUserProfileFromObservation ){ - - // let observationDetails = await surveyService.observationDetails( - // userToken, - // bodyData.submissions.observationId - // ); - - // if( observationDetails.data && - // Object.keys(observationDetails.data).length > 0 && - // observationDetails.data.userRoleInformation && - // Object.keys(observationDetails.data.userRoleInformation).length > 0 - // ) { - - // userRoleInformation = observationDetails.data.userRoleInformation; + // fetch userRoleInformation from observation if referenecFrom is observation + let addReportInfoToSolution = false; + if ( getUserProfileFromObservation ){ + + let observationDetails = await surveyService.observationDetails( + userToken, + bodyData.submissions.observationId + ); + + if( observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userRoleInformation && + Object.keys(observationDetails.data.userRoleInformation).length > 0 + ) { + + userRoleInformation = observationDetails.data.userRoleInformation; - // } + } - // if( observationDetails.data && - // Object.keys(observationDetails.data).length > 0 && - // observationDetails.data.userProfile && - // Object.keys(observationDetails.data.userProfile).length > 0 - // ) { + if( observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userProfile && + Object.keys(observationDetails.data.userProfile).length > 0 + ) { - // projectCreation.data.userProfile = observationDetails.data.userProfile; - // addReportInfoToSolution = true; + projectCreation.data.userProfile = observationDetails.data.userProfile; + addReportInfoToSolution = true; - // } else { - // //Fetch user profile information by calling sunbird's user read api. - - // let userProfile = await userProfileService.profile(userToken, userId); - // if ( userProfile.success && - // userProfile.data && - // userProfile.data.response - // ) { - // projectCreation.data.userProfile = userProfile.data.response; - // addReportInfoToSolution = true; - // } - // } - - // } else { - // //Fetch user profile information by calling sunbird's user read api. - - // let userProfileData = await userProfileService.profile(userToken, userId); - // if ( userProfileData.success && - // userProfileData.data && - // userProfileData.data.response - // ) { - // projectCreation.data.userProfile = userProfileData.data.response; - // addReportInfoToSolution = true; - // } - // } + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfile = await userProfileService.profile(userToken, userId); + if ( userProfile.success && + userProfile.data && + userProfile.data.response + ) { + projectCreation.data.userProfile = userProfile.data.response; + addReportInfoToSolution = true; + } + } + + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfileData = await userProfileService.profile(userToken, userId); + if ( userProfileData.success && + userProfileData.data && + userProfileData.data.response + ) { + projectCreation.data.userProfile = userProfileData.data.response; + addReportInfoToSolution = true; + } + } projectCreation.data.userRoleInformation = userRoleInformation; @@ -1327,12 +1327,12 @@ module.exports = class UserProjectsHelper { let project = await projectQueries.createProject(projectCreation.data); - // if ( addReportInfoToSolution && project.solutionId ) { - // let updateSolution = await solutionsHelper.addReportInformationInSolution( - // project.solutionId, - // project.userProfile - // ); - // } + if ( addReportInfoToSolution && project.solutionId ) { + let updateSolution = await solutionsHelper.addReportInformationInSolution( + project.solutionId, + project.userProfile + ); + } await kafkaProducersHelper.pushProjectToKafka(project); @@ -1977,10 +1977,10 @@ module.exports = class UserProjectsHelper { let programJoined = await programUsers.findProgramIds(userId) projects.data.data = projects.data.data.map((e,i)=>{ - let temp = programJoined.find((element)=> { + let programsIds = programJoined.find((element)=> { return element.programId.toString() == e.programId.toString() }) - if(temp.programId) { + if(programsIds.programId) { e.programJoined = true; } return e; From eebfda9d3eaa211efa695d9a5555cf368c2da604 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 14 Feb 2023 09:17:15 +0530 Subject: [PATCH 259/373] Added user Role Information --- module/userProjects/helper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9ae3468b..9ecb248e 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2303,6 +2303,7 @@ module.exports = class UserProjectsHelper { if(programJoined.length == 0){ let programJoinBody = {}; + programJoinBody.userRoleInformation = requestedData.userRoleInformation ? requestedData.userRoleInformation : {}; programJoinBody.isResource = true; let joinProgramData = await coreService.programJoin ( solutionDetails.programId, From 4766648fe3368572fc99677d27af03d7e391302e Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Sat, 18 Feb 2023 09:03:25 +0530 Subject: [PATCH 260/373] hasAcceptedTAndC check added to importFromLibrary API --- module/userProjects/helper.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index fc46cf9b..2283a2f1 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2307,6 +2307,10 @@ module.exports = class UserProjectsHelper { libraryProjects.data.endDate = requestedData.endDate; } + if (requestedData.hasAcceptedTAndC) { + libraryProjects.data.hasAcceptedTAndC = true; + } + libraryProjects.data.projectTemplateId = libraryProjects.data._id; libraryProjects.data.projectTemplateExternalId = libraryProjects.data.externalId; From b77f5de68ca52c356e76773c5df1eb84c865f71f Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Thu, 23 Feb 2023 18:13:23 +0530 Subject: [PATCH 261/373] env check issue fix --- envVariables.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/envVariables.js b/envVariables.js index 307f75b3..5228d7ef 100644 --- a/envVariables.js +++ b/envVariables.js @@ -143,10 +143,7 @@ module.exports = function() { } async function getKid(){ - if ( enviromentVariables["PROJECT_CERTIFICATE_ON_OFF"] && - enviromentVariables["PROJECT_CERTIFICATE_ON_OFF"].default && - enviromentVariables["PROJECT_CERTIFICATE_ON_OFF"].default === "ON" - ) { + if ( process.env.PROJECT_CERTIFICATE_ON_OFF === "ON" ) { // get certificate issuer kid from sunbird-RC let kidData = await certificateService.getCertificateIssuerKid(); if( !kidData.success ) { From e29e526fba1a2b65a849de350ecb4ba32c01a5df Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Mar 2023 14:49:09 +0530 Subject: [PATCH 262/373] resolved comments --- databaseQueries/programUsers.js | 96 +++++++++++-------- generics/services/core.js | 12 ++- ...Rxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 + models/programUsers.js | 11 ++- module/project/templates/helper.js | 10 +- module/userProjects/helper.js | 77 +++++++-------- 6 files changed, 115 insertions(+), 94 deletions(-) create mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/databaseQueries/programUsers.js b/databaseQueries/programUsers.js index 451be006..771e18ed 100644 --- a/databaseQueries/programUsers.js +++ b/databaseQueries/programUsers.js @@ -1,45 +1,57 @@ -module.exports= class Programs{ - static findProgramJoined(programId,userId) { - return new Promise(async (resolve, reject) => { - try { - let queryObject = { - programId :programId, - userId: userId - } - - - let programJoinedData = - await database.models.programUsers.find( - queryObject, - {} - ).lean(); - return resolve(programJoinedData); - - } catch (error) { - return reject(error); - } - }); - } - - - static findProgramIds(userId) { +module.exports = class Programs { + static programUsersDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { return new Promise(async (resolve, reject) => { - try { - let queryObject = { - userId: userId - } - - - let programJoinedData = - await database.models.programUsers.find( - queryObject, - {"programId":1} - ).lean(); - return resolve(programJoinedData); - - } catch (error) { - return reject(error); + try { + + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); } - }); + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + + let programJoinedData = await database.models.programUsers + .find(queryObject, projection) + .lean(); + return resolve(programJoinedData); + } catch (error) { + return reject(error); + } + }); + } + + + static update(query, update, options = {}) { + return new Promise(async (resolve, reject) => { + try { + + let programUsers = await database.models.programUsers.findOneAndUpdate( + query, + update, + options + ); + if( !programUsers._id ) { + throw { + message : constants.apiResponses.PROGRAM_USERS_NOT_UPDATED + }; + } + return resolve(programUsers); + + } catch (error) { + return reject(error); + } + }) } -} \ No newline at end of file +}; diff --git a/generics/services/core.js b/generics/services/core.js index 9fe6d6a3..80421953 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -729,7 +729,7 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution * program Join Api. * @function * @name programJoin - * @param {String} token - User token. + * @param {String} userToken - User token. * @param {Object} bodyData - Requested body data. * @param {String} programId - program id. * @returns {JSON} - Program Join Status. @@ -748,6 +748,16 @@ const programJoin = function (programId,bodyData,userToken) { }, json: bodyData }; + + if ( bodyData.appVersion !== "" ) { + options.headers.appversion = bodyData.appVersion; + delete bodyData.appVersion + } + + if ( bodyData.appName !== "" ) { + options.headers.appname = bodyData.appName; + delete bodyData.appName + } request.post(url,options,kendraCallback); function kendraCallback(err, data) { diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA new file mode 100644 index 00000000..44c17f6c --- /dev/null +++ b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB +-----END PUBLIC KEY----- diff --git a/models/programUsers.js b/models/programUsers.js index ed287107..447e7e45 100644 --- a/models/programUsers.js +++ b/models/programUsers.js @@ -8,13 +8,18 @@ module.exports = { }, userId: { type: String, - index: true + index: true, + required: true, }, noOfResourcesStarted: { type:Number, - index: true + index: true, + default: 0 + }, + userProfile: { + type : Object, + required: true }, - userProfile: Object, userRoleInformation: Object, appInformation: Object }, diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 41f84739..98ac6ce3 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1081,15 +1081,15 @@ module.exports = class ProjectTemplatesHelper { },["_id"]); //check for program enrollment if enrolled then add programJoined true - let programJoined = await programUsers.findProgramIds(userId) - let projects = project.map((e,i)=>{ - let programIds = programJoined.find((element)=> { - return element.programId.toString() == e._id.toString() + let programJoined = await programUsers.programUsersDocument({userId: userId},["programId"]) + project.map((projects)=>{ + let programIds = programJoined.find((program)=> { + return program.programId.toString() == projects._id.toString() }) if(programIds.programId) { templateData[0].programJoined = true; } - return e; + return projects; }) if(project && project.length > 0){ diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9ecb248e..2ea4fdb6 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1115,25 +1115,34 @@ module.exports = class UserProjectsHelper { } // program join API call - let programJoined = await programUsers.findProgramJoined(solutionDetails.programId,userId) - console.log(programJoined) - if(programJoined.length == 0){ - - let programJoinBody = {}; - programJoinBody.userRoleInformation = bodyData; - programJoinBody.isResource = true; - let joinProgramData = await coreService.programJoin ( - solutionDetails.programId, - programJoinBody, - userToken - ); - if ( !joinProgramData.success ) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - }); + if ( appVersion === "" || appVersion < 5.2 ) { + let query = { + userId: userId, + programId: solutionDetails.programId } + let programJoined = await programUsers.programUsersDocument(query) + if(programJoined.length == 0){ + let programJoinBody = {}; + programJoinBody.userRoleInformation = bodyData; + programJoinBody.isResource = true; + let joinProgramData = await coreService.programJoin ( + solutionDetails.programId, + programJoinBody, + userToken + ); + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); + } + }else{ + await programUsers.update( + { _id : programUsers[0]._id }, + { '$inc' : { noOfResourcesStarted : 1 } } + ); + } } let projectCreation = @@ -1974,16 +1983,17 @@ module.exports = class UserProjectsHelper { let totalCount = 0; let data = []; - - let programJoined = await programUsers.findProgramIds(userId) - projects.data.data = projects.data.data.map((e,i)=>{ - let programsIds = programJoined.find((element)=> { - return element.programId.toString() == e.programId.toString() + //this is to check if user has already joined program or not + let programJoined = await programUsers.programUsersDocument({userId: userId},["programId"]) + projects.data.data = projects.data.data.map((project)=>{ + //maps projects which have joined program + let programsIds = programJoined.find((program)=> { + return program.programId.toString() == project.programId.toString() }) if(programsIds.programId) { - e.programJoined = true; + project.programJoined = true; } - return e; + return project; }) if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { @@ -2299,25 +2309,6 @@ module.exports = class UserProjectsHelper { ) } - let programJoined = await programUsers.findProgramJoined(requestedData.programId,userId) - if(programJoined.length == 0){ - - let programJoinBody = {}; - programJoinBody.userRoleInformation = requestedData.userRoleInformation ? requestedData.userRoleInformation : {}; - programJoinBody.isResource = true; - let joinProgramData = await coreService.programJoin ( - solutionDetails.programId, - programJoinBody, - userToken - ); - if ( !joinProgramData.success ) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - }); - } - - } // <- Add certificate template data if ( From 31c72e5636dd646a9cd2bcc6abc6f0e40ca03928 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Mar 2023 14:49:26 +0530 Subject: [PATCH 263/373] resolved comments --- .../GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA deleted file mode 100644 index 44c17f6c..00000000 --- a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB ------END PUBLIC KEY----- From f078a0481c1c3a64d2e9058e50d7b4da48619759 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Mar 2023 14:51:36 +0530 Subject: [PATCH 264/373] resolved comments --- generics/services/core.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/generics/services/core.js b/generics/services/core.js index 80421953..0ada43bf 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -746,7 +746,7 @@ const programJoin = function (programId,bodyData,userToken) { "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, "x-authenticated-user-token" : userToken, }, - json: bodyData + }; if ( bodyData.appVersion !== "" ) { @@ -758,6 +758,9 @@ const programJoin = function (programId,bodyData,userToken) { options.headers.appname = bodyData.appName; delete bodyData.appName } + + + options.json = bodyData request.post(url,options,kendraCallback); function kendraCallback(err, data) { From f1a910c1ff3cc67d5616715472fa2a8f9c11a5d0 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 8 Mar 2023 15:37:01 +0530 Subject: [PATCH 265/373] resolved comments --- databaseQueries/programUsers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/databaseQueries/programUsers.js b/databaseQueries/programUsers.js index 771e18ed..b4dc37b4 100644 --- a/databaseQueries/programUsers.js +++ b/databaseQueries/programUsers.js @@ -1,4 +1,4 @@ -module.exports = class Programs { +module.exports = class programUsers { static programUsersDocument( filterData = "all", fieldsArray = "all", From 5f4858cdb2e20801af5ce8434afb20ca6d8eccd8 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Mar 2023 11:28:09 +0530 Subject: [PATCH 266/373] fix for ED-1463 --- ...Rxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 +++ module/reports/helper.js | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA new file mode 100644 index 00000000..44c17f6c --- /dev/null +++ b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB +-----END PUBLIC KEY----- diff --git a/module/reports/helper.js b/module/reports/helper.js index a07f2ec5..71f3abb5 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -349,6 +349,7 @@ module.exports = class ReportsHelper { return new Promise(async (resolve, reject) => { try { + console.log(entityId) let query = { "userId": userId, programId : { @@ -359,15 +360,15 @@ module.exports = class ReportsHelper { if( entityId != "" ) { query.entityId = entityId; } - - if (userRole != "") { - query.userRole = { - $in : [ - "", - ...userRole.split(",") - ] - } - } + // not able to find programs which user started it will match only exact string + // if (userRole != "") { + // query.userRole = { + // $in : [ + // "", + // ...userRole.split(",") + // ] + // } + // } let searchQuery = []; if (search !== "") { From 1b34fdf5d67cd435b24ccc46c19221baf82bec78 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Mar 2023 12:52:50 +0530 Subject: [PATCH 267/373] fixed program listing --- module/reports/helper.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/module/reports/helper.js b/module/reports/helper.js index 71f3abb5..b5b0c35d 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -360,15 +360,15 @@ module.exports = class ReportsHelper { if( entityId != "" ) { query.entityId = entityId; } - // not able to find programs which user started it will match only exact string - // if (userRole != "") { - // query.userRole = { - // $in : [ - // "", - // ...userRole.split(",") - // ] - // } - // } + + if (userRole != "") { + let regex = userRole.split(","); + regex.push("") + query.userRole = { + $regex:regex.join("|"), + $options: "i" + } + } let searchQuery = []; if (search !== "") { From fe31eb72716cc12590fb4dffff025839c821ebc3 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Mar 2023 12:53:26 +0530 Subject: [PATCH 268/373] fixed program listing --- .../GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA deleted file mode 100644 index 44c17f6c..00000000 --- a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB ------END PUBLIC KEY----- From 172ebdfbf3539658ab79f9c223e8997fb87f953f Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Mar 2023 12:54:39 +0530 Subject: [PATCH 269/373] fixed program listing --- module/reports/helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/module/reports/helper.js b/module/reports/helper.js index b5b0c35d..9318a6a2 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -349,7 +349,6 @@ module.exports = class ReportsHelper { return new Promise(async (resolve, reject) => { try { - console.log(entityId) let query = { "userId": userId, programId : { From f68f14f2bc4ef5b08f423ced1b706f87841f379c Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Mar 2023 17:00:47 +0530 Subject: [PATCH 270/373] fixed non targeted to targeted project issue --- module/userProjects/helper.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 2283a2f1..665ce211 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1069,10 +1069,16 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { - + const userRoleInformations = userRoleInformation.role.split(",") + userRoleInformations.push() const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, - userId: userId + userId: userId, + userRole:{ + $regex: userRoleInformations.join("|"), + $options: "i" + }, + "userRoleInformation.state": userRoleInformation.state }, ["_id"]); if( projectDetails.length > 0 ) { From 48a7533056e28c4a16b45e51a04e2cb32fdf3def Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Mar 2023 17:03:35 +0530 Subject: [PATCH 271/373] fixed non targeted to targeted project issue --- module/userProjects/helper.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 2283a2f1..665ce211 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1069,10 +1069,16 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { - + const userRoleInformations = userRoleInformation.role.split(",") + userRoleInformations.push() const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, - userId: userId + userId: userId, + userRole:{ + $regex: userRoleInformations.join("|"), + $options: "i" + }, + "userRoleInformation.state": userRoleInformation.state }, ["_id"]); if( projectDetails.length > 0 ) { From 947561874c4f3bb9180cb44e310753670ff569f1 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 24 Mar 2023 18:53:22 +0530 Subject: [PATCH 272/373] added integrated api to check solution is targeted or not --- generics/constants/endpoints.js | 3 +- generics/services/core.js | 54 ++++++++++++++++++++++++++++++++- module/userProjects/helper.js | 11 +++---- 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index c8a5bfaf..3fbded51 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -51,5 +51,6 @@ module.exports = { CERTIFICATE_CREATE : "/api/v1/ProjectCertificate", PROJECT_CERTIFICATE_API_CALLBACK : "/v1/userProjects/certificateCallback", USER_READ_PRIVATE : "/private/user/v1/read", // !Caution: End point for reading user details without token. Do not use for public work flow - GET_CERTIFICATE_KID : "/api/v1/PublicKey/search" + GET_CERTIFICATE_KID : "/api/v1/PublicKey/search", + VERIFY_TARGETED_SOLUTION : "/v1/solutions/verfiySolution", }; diff --git a/generics/services/core.js b/generics/services/core.js index ec12900e..a77d0204 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -725,6 +725,57 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution }) } + +const verifyTargetedSolution = function ( token,bodyData,solutionId ) { + return new Promise(async (resolve, reject) => { + try { + + const url = + ML_CORE_URL + CONSTANTS.endpoints.VERIFY_TARGETED_SOLUTION + "/" + solutionId; + + const options = { + headers : { + "content-type": "application/json", + "internal-access-token": process.env.INTERNAL_ACCESS_TOKEN, + "x-authenticated-user-token" : token + }, + json : bodyData + }; + + request.post(url,options,varifyTergetedSolutionCallbeck); + + function varifyTergetedSolutionCallbeck(err, data) { + + let result = { + success : true + }; + + if (err) { + result.success = false; + } else { + + let response = data.body; + if( response.status === HTTP_STATUS_CODE['ok'].status ) { + result["data"] = response.result; + } else { + result.success = false; + } + } + + return resolve(result); + } + + } catch (error) { + return reject(error); + } + }) +} + + + + + + module.exports = { entityTypesDocuments : entityTypesDocuments, rolesDocuments : rolesDocuments, @@ -738,6 +789,7 @@ module.exports = { createSolution: createSolution, solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, - getDownloadableUrl : getDownloadableUrl + getDownloadableUrl : getDownloadableUrl, + verifyTargetedSolution:verifyTargetedSolution }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 665ce211..fbb6f219 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1069,16 +1069,13 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { - const userRoleInformations = userRoleInformation.role.split(",") - userRoleInformations.push() + + const targetedSolutionId = await coreService.verifyTargetedSolution(userToken,bodyData,solutionId) + const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, userId: userId, - userRole:{ - $regex: userRoleInformations.join("|"), - $options: "i" - }, - "userRoleInformation.state": userRoleInformation.state + isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true }, ["_id"]); if( projectDetails.length > 0 ) { From 0518231629e61f2cc73ebd83e6d8b6041f428a0d Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 24 Mar 2023 18:54:29 +0530 Subject: [PATCH 273/373] added integrated api to check solution is targeted or not --- generics/services/core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index a77d0204..1f960198 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -742,9 +742,9 @@ const verifyTargetedSolution = function ( token,bodyData,solutionId ) { json : bodyData }; - request.post(url,options,varifyTergetedSolutionCallbeck); + request.post(url,options,verifyTergetedSolutionCallbeck); - function varifyTergetedSolutionCallbeck(err, data) { + function verifyTergetedSolutionCallbeck(err, data) { let result = { success : true From 7a5d78ddb254ff73cdb6d28a00db0c41dd54da4d Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 24 Mar 2023 19:09:41 +0530 Subject: [PATCH 274/373] added integrated api to check solution is targeted or not --- generics/constants/endpoints.js | 2 +- generics/services/core.js | 6 +++--- module/userProjects/helper.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/generics/constants/endpoints.js b/generics/constants/endpoints.js index 3fbded51..bec01de6 100644 --- a/generics/constants/endpoints.js +++ b/generics/constants/endpoints.js @@ -52,5 +52,5 @@ module.exports = { PROJECT_CERTIFICATE_API_CALLBACK : "/v1/userProjects/certificateCallback", USER_READ_PRIVATE : "/private/user/v1/read", // !Caution: End point for reading user details without token. Do not use for public work flow GET_CERTIFICATE_KID : "/api/v1/PublicKey/search", - VERIFY_TARGETED_SOLUTION : "/v1/solutions/verfiySolution", + IS_TARGETED_BASED_ON_USER_PROFILE : "/v1/solutions/isTargetedBasedOnUserProfile", }; diff --git a/generics/services/core.js b/generics/services/core.js index 1f960198..65c72266 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -726,12 +726,12 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution } -const verifyTargetedSolution = function ( token,bodyData,solutionId ) { +const isTargetedBasedOnUserProfile = function ( token,bodyData,solutionId ) { return new Promise(async (resolve, reject) => { try { const url = - ML_CORE_URL + CONSTANTS.endpoints.VERIFY_TARGETED_SOLUTION + "/" + solutionId; + ML_CORE_URL + CONSTANTS.endpoints.IS_TARGETED_BASED_ON_USER_PROFILE + "/" + solutionId; const options = { headers : { @@ -790,6 +790,6 @@ module.exports = { solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, getDownloadableUrl : getDownloadableUrl, - verifyTargetedSolution:verifyTargetedSolution + isTargetedBasedOnUserProfile:isTargetedBasedOnUserProfile }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index fbb6f219..c22bbaa6 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1070,7 +1070,7 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { - const targetedSolutionId = await coreService.verifyTargetedSolution(userToken,bodyData,solutionId) + const targetedSolutionId = await coreService.isTargetedBasedOnUserProfile(userToken,bodyData,solutionId) const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, From 43787723f9a8c83f067e7401cd4dd55b7fb24a6c Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 24 Mar 2023 19:17:50 +0530 Subject: [PATCH 275/373] added integrated api to check solution is targeted or not --- generics/services/core.js | 4 ++-- module/userProjects/helper.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index 65c72266..8edf078b 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -742,9 +742,9 @@ const isTargetedBasedOnUserProfile = function ( token,bodyData,solutionId ) { json : bodyData }; - request.post(url,options,verifyTergetedSolutionCallbeck); + request.post(url,options,verifyTargetedSolutionCallbeck); - function verifyTergetedSolutionCallbeck(err, data) { + function verifyTargetedSolutionCallbeck(err, data) { let result = { success : true diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c22bbaa6..99ae7641 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1069,9 +1069,9 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { - + // This is used to check solution is targetted or not const targetedSolutionId = await coreService.isTargetedBasedOnUserProfile(userToken,bodyData,solutionId) - + //based on above api will check for projects wether its is private project or public project const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, userId: userId, From d697df9bde5024047f3ff636e0794e315b1a72d8 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 24 Mar 2023 19:19:40 +0530 Subject: [PATCH 276/373] added integrated api to check solution is targeted or not --- generics/services/core.js | 4 ++-- module/userProjects/helper.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index 8edf078b..b4a1e244 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -726,7 +726,7 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution } -const isTargetedBasedOnUserProfile = function ( token,bodyData,solutionId ) { +const checkIfSolutionIsTargetedForUserProfile = function ( token,bodyData,solutionId ) { return new Promise(async (resolve, reject) => { try { @@ -790,6 +790,6 @@ module.exports = { solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, getDownloadableUrl : getDownloadableUrl, - isTargetedBasedOnUserProfile:isTargetedBasedOnUserProfile + checkIfSolutionIsTargetedForUserProfile:checkIfSolutionIsTargetedForUserProfile }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 99ae7641..4cef5064 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1070,7 +1070,7 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { // This is used to check solution is targetted or not - const targetedSolutionId = await coreService.isTargetedBasedOnUserProfile(userToken,bodyData,solutionId) + const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,bodyData,solutionId) //based on above api will check for projects wether its is private project or public project const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, From df010cbcdfd27b415d7250d7aa1834faebbdfc4b Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 27 Mar 2023 14:01:01 +0530 Subject: [PATCH 277/373] fixed code --- generics/services/core.js | 4 ++-- module/userProjects/helper.js | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index b4a1e244..8a1ace5c 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -742,9 +742,9 @@ const checkIfSolutionIsTargetedForUserProfile = function ( token,bodyData,soluti json : bodyData }; - request.post(url,options,verifyTargetedSolutionCallbeck); + request.post(url,options,verifyTargetedSolutionCallback); - function verifyTargetedSolutionCallbeck(err, data) { + function verifyTargetedSolutionCallback(err, data) { let result = { success : true diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4cef5064..090b503f 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1071,12 +1071,18 @@ module.exports = class UserProjectsHelper { if (projectId === "") { // This is used to check solution is targetted or not const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,bodyData,solutionId) - //based on above api will check for projects wether its is private project or public project - const projectDetails = await projectQueries.projectDocument({ + + let projectDocumentQuery = { solutionId: solutionId, userId: userId, - isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true - }, ["_id"]); + } + + if(targetedSolutionId.data.isATargetedSolution){ + projectDocumentQuery.isAPrivateProgram = false + } + //based on above api will check for projects wether its is private project or public project + const projectDetails = await projectQueries.projectDocument(projectDocumentQuery, ["_id"]); + if( projectDetails.length > 0 ) { projectId = projectDetails[0]._id; From 52e557331005434ce64c0ffd150dae80acc68e2f Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 28 Mar 2023 02:23:59 +0530 Subject: [PATCH 278/373] Fixed Public and private project for solution --- controllers/v1/project/templates.js | 3 ++- module/project/templates/helper.js | 5 +++-- module/userProjects/helper.js | 17 +++++------------ 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/controllers/v1/project/templates.js b/controllers/v1/project/templates.js index 486ad6c2..1cc19f70 100644 --- a/controllers/v1/project/templates.js +++ b/controllers/v1/project/templates.js @@ -680,7 +680,8 @@ module.exports = class ProjectTemplates extends Abstract { await projectTemplatesHelper.details( req.params._id ? req.params._id : "", req.query.link ? req.query.link : "", - req.userDetails && req.userDetails.userInformation && req.userDetails.userInformation.userId ? req.userDetails.userInformation.userId : "" + req.userDetails && req.userDetails.userInformation && req.userDetails.userInformation.userId ? req.userDetails.userInformation.userId : "", + req.query.isAPrivateProgram ? req.query.isAPrivateProgram : "" ); projectTemplatesDetails.result = projectTemplatesDetails.data; diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 6e3404f8..26081a25 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -975,7 +975,7 @@ module.exports = class ProjectTemplatesHelper { * @returns {Array} Project templates data. */ - static details( templateId="", link="", userId="" ) { + static details( templateId="", link="", userId="", isAPrivateProgram ) { return new Promise(async (resolve, reject) => { try { let solutionsResult = {}; @@ -1077,7 +1077,8 @@ module.exports = class ProjectTemplatesHelper { let project = await projectQueries.projectDocument({ userId : userId, - projectTemplateId : templateData[0]._id + projectTemplateId : templateData[0]._id, + isAPrivateProgram : isAPrivateProgram },["_id"]); if(project && project.length > 0){ diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 090b503f..f35f82a3 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1069,21 +1069,14 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { - // This is used to check solution is targetted or not + // This will check wether the user user is targeted to solution or not based on his userRoleInformation const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,bodyData,solutionId) - - let projectDocumentQuery = { + //based on above api will check for projects wether its is private project or public project + const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, userId: userId, - } - - if(targetedSolutionId.data.isATargetedSolution){ - projectDocumentQuery.isAPrivateProgram = false - } - //based on above api will check for projects wether its is private project or public project - const projectDetails = await projectQueries.projectDocument(projectDocumentQuery, ["_id"]); - - + isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true + }, ["_id"]); if( projectDetails.length > 0 ) { projectId = projectDetails[0]._id; } else { From d9b0420636a9501e93067bd413613fb3e990729f Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 28 Mar 2023 11:57:05 +0530 Subject: [PATCH 279/373] Fixed Public and private project for solution --- module/project/templates/helper.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 26081a25..cff8689c 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1074,11 +1074,18 @@ module.exports = class ProjectTemplatesHelper { if( !templateData[0].isReusable && userId !== "") { templateData[0].projectId = ""; - - let project = await projectQueries.projectDocument({ + + const projectIdQuery = { userId : userId, projectTemplateId : templateData[0]._id, - isAPrivateProgram : isAPrivateProgram + } + + if( isAPrivateProgram !== ""){ + projectIdQuery.isAPrivateProgram = isAPrivateProgram + } + + let project = await projectQueries.projectDocument({ + projectIdQuery },["_id"]); if(project && project.length > 0){ From c5ac1c7de293bac62395ea9fa44549e8617a2f68 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 28 Mar 2023 13:14:06 +0530 Subject: [PATCH 280/373] Fixed Public and private project for solution --- app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 066afc79..30806a0d 100644 --- a/app.js +++ b/app.js @@ -45,12 +45,12 @@ app.use(express.static("public")); app.all('*', (req, res, next) => { console.log({"Debugging ML Projects Service": true}); - console.log("-------Request log starts here------------------"); + console.log("<------------Request log starts here------------------>"); console.log("Request URL: ", req.url); console.log("Request Headers: ", JSON.stringify(req.headers)); console.log("Request Body: ", JSON.stringify(req.body)); // console.log("Request Files: ", req.files); - console.log("-------Request log ends here------------------"); + console.log("<---------------Request log ends here------------------>"); next(); }); From 243d700fc7d9f5c0063a618b06addae801a6231b Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 6 Apr 2023 07:49:41 +0530 Subject: [PATCH 281/373] fixed comments' --- generics/services/core.js | 6 +-- ...Rxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 ++ module/project/templates/helper.js | 11 ----- module/userProjects/helper.js | 45 +++++++------------ 4 files changed, 22 insertions(+), 43 deletions(-) create mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/generics/services/core.js b/generics/services/core.js index 0ada43bf..10ef42a9 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -728,13 +728,13 @@ const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solution /** * program Join Api. * @function - * @name programJoin + * @name joinProgram * @param {String} userToken - User token. * @param {Object} bodyData - Requested body data. * @param {String} programId - program id. * @returns {JSON} - Program Join Status. */ -const programJoin = function (programId,bodyData,userToken) { +const joinProgram = function (programId,bodyData,userToken) { return new Promise(async (resolve, reject) => { try { @@ -803,6 +803,6 @@ module.exports = { solutionBasedOnRoleAndLocation : solutionBasedOnRoleAndLocation, solutionDetailsBasedOnRoleAndLocation : solutionDetailsBasedOnRoleAndLocation, getDownloadableUrl : getDownloadableUrl, - programJoin: programJoin + joinProgram: joinProgram }; diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA new file mode 100644 index 00000000..44c17f6c --- /dev/null +++ b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB +-----END PUBLIC KEY----- diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 98ac6ce3..5b2ca248 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1080,17 +1080,6 @@ module.exports = class ProjectTemplatesHelper { projectTemplateId : templateData[0]._id },["_id"]); - //check for program enrollment if enrolled then add programJoined true - let programJoined = await programUsers.programUsersDocument({userId: userId},["programId"]) - project.map((projects)=>{ - let programIds = programJoined.find((program)=> { - return program.programId.toString() == projects._id.toString() - }) - if(programIds.programId) { - templateData[0].programJoined = true; - } - return projects; - }) if(project && project.length > 0){ templateData[0].projectId = project[0]._id; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 2ea4fdb6..56bfd4f5 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1114,35 +1114,22 @@ module.exports = class UserProjectsHelper { solutionDetails = solutionDetails.data[0]; } - // program join API call - if ( appVersion === "" || appVersion < 5.2 ) { - let query = { - userId: userId, - programId: solutionDetails.programId - } - let programJoined = await programUsers.programUsersDocument(query) - if(programJoined.length == 0){ - - let programJoinBody = {}; - programJoinBody.userRoleInformation = bodyData; - programJoinBody.isResource = true; - let joinProgramData = await coreService.programJoin ( - solutionDetails.programId, - programJoinBody, - userToken - ); - if ( !joinProgramData.success ) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - }); - } - }else{ - await programUsers.update( - { _id : programUsers[0]._id }, - { '$inc' : { noOfResourcesStarted : 1 } } - ); - } + + // program join API call it will increment the noOfResourcesStarted counter and will make user join program + // before creating any project this api has to called + let programJoinBody = {}; + programJoinBody.userRoleInformation = bodyData; + programJoinBody.isResource = true; + let joinProgramData = await coreService.joinProgram ( + solutionDetails.programId, + programJoinBody, + userToken + ); + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); } let projectCreation = From 73fa151fc1b9919feebbbd03b5e2f9afd0d2d7d1 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 6 Apr 2023 07:50:01 +0530 Subject: [PATCH 282/373] fixed comments --- .../GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA deleted file mode 100644 index 44c17f6c..00000000 --- a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB ------END PUBLIC KEY----- From 7eb8d542cc7f65401225a9184a64d7678c92e09d Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 6 Apr 2023 11:14:39 +0530 Subject: [PATCH 283/373] fixed comments --- databaseQueries/programUsers.js | 22 ---------------------- module/userProjects/helper.js | 12 ------------ 2 files changed, 34 deletions(-) diff --git a/databaseQueries/programUsers.js b/databaseQueries/programUsers.js index b4dc37b4..f96cb292 100644 --- a/databaseQueries/programUsers.js +++ b/databaseQueries/programUsers.js @@ -32,26 +32,4 @@ module.exports = class programUsers { }); } - - static update(query, update, options = {}) { - return new Promise(async (resolve, reject) => { - try { - - let programUsers = await database.models.programUsers.findOneAndUpdate( - query, - update, - options - ); - if( !programUsers._id ) { - throw { - message : constants.apiResponses.PROGRAM_USERS_NOT_UPDATED - }; - } - return resolve(programUsers); - - } catch (error) { - return reject(error); - } - }) -} }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 56bfd4f5..ae76b362 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1970,18 +1970,6 @@ module.exports = class UserProjectsHelper { let totalCount = 0; let data = []; - //this is to check if user has already joined program or not - let programJoined = await programUsers.programUsersDocument({userId: userId},["programId"]) - projects.data.data = projects.data.data.map((project)=>{ - //maps projects which have joined program - let programsIds = programJoined.find((program)=> { - return program.programId.toString() == project.programId.toString() - }) - if(programsIds.programId) { - project.programJoined = true; - } - return project; - }) if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { totalCount = projects.data.count; From 41a9314b87a46b538388a6d8a310b2eb144cecc6 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 7 Apr 2023 14:58:43 +0530 Subject: [PATCH 284/373] resolved conflict --- .../GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA diff --git a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA b/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA deleted file mode 100644 index 44c17f6c..00000000 --- a/keycloak-public-keys/GRxx8ur43pXH3_QMzBWerQPWrX02PJkK9Czl3hc60fA +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoRbRlp/1x0h5a9Rb3E7+nU17mdnU1Grv2/a6ixhdBr1f9mjKEn7F/5eIfCQL3H82stxZyskeWaetL1mNJkAHFcJx+03DoKnGP6K+PZ3Svbw67ehgqyp+OozZCNXHzrM1DUVpvhYgsnvkqm+E1QyrsmrghSE+bAHqJep4S/70z12t8rwMNB6OxcbhrHBU93TxszxHHLZL9eaa2DCwGsTbYml0V2vFPsN4HUhXtnht9uoC2bjAXyBsrSNy/aoCsoI0erV8Vyw2FKfwEGBDFROjcWhKOdwb36TmEDf+g4OBSqAhEyewhTwcP7ESpjhyA3Ae1cH9cKOBmQTU+OmzS89h8QIDAQAB ------END PUBLIC KEY----- From d383bf79eec7202010b581a81920f769984fdd47 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 7 Apr 2023 15:25:49 +0530 Subject: [PATCH 285/373] resolved conflicts --- module/project/templates/helper.js | 2 +- module/userProjects/helper.js | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 73f326d4..cff8689c 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1079,6 +1079,7 @@ module.exports = class ProjectTemplatesHelper { userId : userId, projectTemplateId : templateData[0]._id, } + if( isAPrivateProgram !== ""){ projectIdQuery.isAPrivateProgram = isAPrivateProgram } @@ -1086,7 +1087,6 @@ module.exports = class ProjectTemplatesHelper { let project = await projectQueries.projectDocument({ projectIdQuery },["_id"]); - if(project && project.length > 0){ templateData[0].projectId = project[0]._id; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6a6aea92..83a11929 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1070,18 +1070,6 @@ module.exports = class UserProjectsHelper { let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { -<<<<<<< HEAD - const userRoleInformations = userRoleInformation.role.split(",") - userRoleInformations.push() - const projectDetails = await projectQueries.projectDocument({ - solutionId: solutionId, - userId: userId, - userRole:{ - $regex: userRoleInformations.join("|"), - $options: "i" - }, - "userRoleInformation.state": userRoleInformation.state -======= // This will check wether the user user is targeted to solution or not based on his userRoleInformation const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,bodyData,solutionId) //based on above api will check for projects wether its is private project or public project @@ -1089,7 +1077,6 @@ module.exports = class UserProjectsHelper { solutionId: solutionId, userId: userId, isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true ->>>>>>> refs/remotes/origin/master }, ["_id"]); if( projectDetails.length > 0 ) { projectId = projectDetails[0]._id; From bc836f113b9e27f945abe0cd0d0c6e74d2d30440 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 7 Apr 2023 15:30:33 +0530 Subject: [PATCH 286/373] resolved conflicts --- controllers/v1/programUsers.js | 2 +- databaseQueries/programUsers.js | 17 +++++++++++++++++ module/userProjects/helper.js | 2 -- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/controllers/v1/programUsers.js b/controllers/v1/programUsers.js index 3a9c4923..35d8ef63 100644 --- a/controllers/v1/programUsers.js +++ b/controllers/v1/programUsers.js @@ -1,6 +1,6 @@ /** * name : programUsers.js - * author : Vishnu + * author : Ankit Shahu * created-date : 9-Jan-2023 * Description : PII data related controller. */ diff --git a/databaseQueries/programUsers.js b/databaseQueries/programUsers.js index f96cb292..479b8b8e 100644 --- a/databaseQueries/programUsers.js +++ b/databaseQueries/programUsers.js @@ -1,4 +1,21 @@ +/** + * name : programUsers.js + * author : Ankit Shahu + * created-date : 07-04-2023 + * Description : program users helper for DB interactions. + */ module.exports = class programUsers { + + /** + * program users details. + * @method + * @name programUsersDocument + * @param {Array} [filterData = "all"] - program users filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} program users details. + */ + static programUsersDocument( filterData = "all", fieldsArray = "all", diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 83a11929..722298b5 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2285,8 +2285,6 @@ module.exports = class UserProjectsHelper { programAndSolutionInformation.data ) } - - // <- Add certificate template data if ( libraryProjects.data.certificateTemplateId && From 7cd790e603ce26656167d825bc97a1b951b594c6 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 11 Apr 2023 19:18:56 +0530 Subject: [PATCH 287/373] Done with ED-98 Project PII --- .gitignore | 1 + models/programUsers.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index ede208e0..90cf764a 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,4 @@ config/credentials/* *.DS_Store package-lock.json +keycloak-public-keys/ \ No newline at end of file diff --git a/models/programUsers.js b/models/programUsers.js index 447e7e45..58b00a3e 100644 --- a/models/programUsers.js +++ b/models/programUsers.js @@ -11,10 +11,10 @@ module.exports = { index: true, required: true, }, - noOfResourcesStarted: { - type:Number, + resourcesStarted: { + type: Boolean, index: true, - default: 0 + default: false }, userProfile: { type : Object, From 504994266739d962ebaf36bd3bae0d8599b18a1d Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 11 Apr 2023 19:54:42 +0530 Subject: [PATCH 288/373] Added validation for program join API --- module/userProjects/helper.js | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 722298b5..71e341b2 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -28,6 +28,7 @@ const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTem const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); const certificateValidationsHelper = require(MODULES_BASE_PATH + "/certificateValidations/helper"); const _ = require("lodash"); +const programUsersQueries = require(DB_QUERY_BASE_PATH + "/programUsers"); /** * UserProjectsHelper @@ -1119,21 +1120,33 @@ module.exports = class UserProjectsHelper { // program join API call it will increment the noOfResourcesStarted counter and will make user join program // before creating any project this api has to called - let programJoinBody = {}; - programJoinBody.userRoleInformation = bodyData; - programJoinBody.isResource = true; - let joinProgramData = await coreService.joinProgram ( - solutionDetails.programId, - programJoinBody, - userToken + let programUsers = await programUsersQueries.programUsersDocuments( + { + userId : userId, + programId : solutionDetails.programId + }, + [ + "_id", + "resourcesStarted" + ] ); - if ( !joinProgramData.success ) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - }); + + if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { + let programJoinBody = {}; + programJoinBody.userRoleInformation = bodyData; + programJoinBody.isResource = true; + let joinProgramData = await coreService.joinProgram ( + solutionDetails.programId, + programJoinBody, + userToken + ); + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); + } } - let projectCreation = await this.userAssignedProjectCreation( solutionDetails.projectTemplateId, From 62a62fbf49f84687d3cf9816c4feef8005feb4cb Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 2 May 2023 12:33:40 +0530 Subject: [PATCH 289/373] Added PR checklist --- .github/pull_request_template.md | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..bb5dc77f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,36 @@ + +# Description +These recommendations are intended to promote code quality and team communication during software development. They cover a variety of topics, including ensuring that pull requests are submitted to the correct branch, documenting new methods, preserving consistency across many services, and avoiding typical blunders like accessing APIs or DB queries within loops. Sensitive data should not be uploaded, and changes to environment variables or database models should be executed consistently. Teams may work more effectively and develop higher-quality software by adhering to these standards. + + +## Type of change +Please choose appropriate options. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Enhancement (additive changes to improve performance) +- [ ] This change requires a documentation update + +## Checklist + +- [ ] It's critical to avoid making needless file modifications in contributions, such as adding new lines, console logs, or additional spaces, to guarantee cleaner and more efficient code. Furthermore, eliminating unnecessary imports from a file might enhance code readability and efficiency. +- [ ] Ensure that the pull request is assigned to the right base branch and that the development branch name contains the JIRA Task Id. Furthermore, each commit message should include the JIRA Task Id in the manner "ED-100: message". +- [ ] Only update packages if it is mentioned and authorized in the design document, and make sure that you have the required permissions. +- [ ] Avoid making API and database queries inside a loop as it can lead to performance issues and slow down the system. +- [ ] When calling another function inside a given function, add comments explaining the purpose and meaning of the passed arguments and expected return values. +- [ ] If adding a blank argument in a function, add a comment explaining the reason for the blank argument. +- [ ] Before submitting a pull request, do a self-review of your code to ensure there are no conflicts with the base branch and all comments have been addressed. +- [ ] Before merging a pull request, it's important to have other team members review it to catch any potential errors or issues +- [ ] To maintain code integrity, it's important to remove all related changes when removing code during a code review. +- [ ] If new constants, endpoints, or utility functions are introduced, it is important to check if they already exist in the service to avoid any duplication. +- [ ] Whenever a new environment variable is added to a service, it's important to ensure that the necessary changes are made to related files such as ".env.sample" and "envVariables.js" to maintain consistency and avoid errors. Additionally, the new environment variable should be added to the devops repository to ensure that it is properly documented and accessible to the team. +- [ ] When adding a new function to a service, it is important to document it with relevant information such as the name, parameters, and return value in a consistent format across all services. Additionally, if there are any changes to the API response, ensure that the documentation in the controllers is updated accordingly. +- [ ] Write a clear and concise commit message that describes the changes made. +- [ ] Maintain consistent function signature and code across all services when adding a function to multiple services. Implement changes to database models in all services that use the same model. +- [ ] Use only let and const. Do not use var. +- [ ] Make common functions for repetitive code blocks. +- [ ] Avoid uploading sensitive information such as secret tokens or passwords in pull requests to ensure data security. +- [ ] Maintain consistent indentation and spacing throughout the code. + + From 0e0e8a138b1f829136c73ea197faeeb3c19f4312 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 9 May 2023 17:16:04 +0530 Subject: [PATCH 290/373] change added to not join old programs internally --- models/programs.js | 9 +++++- module/userProjects/helper.js | 61 +++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/models/programs.js b/models/programs.js index cb411bb3..e4e906b9 100644 --- a/models/programs.js +++ b/models/programs.js @@ -45,6 +45,13 @@ module.exports = { default : false, type : Boolean, index : true - } + }, + requestForPIIConsent: Boolean, + metaInformation: Object, + rootOrganisations : { + type : Array, + require : true + }, + createdFor : Array } }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 71e341b2..9ceb9a24 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -21,7 +21,6 @@ const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplat const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); -const programUsers = require(DB_QUERY_BASE_PATH + "/programUsers"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); @@ -1117,36 +1116,44 @@ module.exports = class UserProjectsHelper { solutionDetails = solutionDetails.data[0]; } + // check for requestForPIIConsent data + let queryData = {}; + queryData["_id"] = solutionDetails.programId; + let programDetails = await programsQueries.programsDocument(queryData,["requestForPIIConsent"]); - // program join API call it will increment the noOfResourcesStarted counter and will make user join program - // before creating any project this api has to called - let programUsers = await programUsersQueries.programUsersDocuments( - { - userId : userId, - programId : solutionDetails.programId - }, - [ - "_id", - "resourcesStarted" - ] - ); - - if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { - let programJoinBody = {}; - programJoinBody.userRoleInformation = bodyData; - programJoinBody.isResource = true; - let joinProgramData = await coreService.joinProgram ( - solutionDetails.programId, - programJoinBody, - userToken + // if requestForPIIConsent not there programDetails will be an empty array + if ( programDetails.length > 0 && programDetails[0].hasOwnProperty('requestForPIIConsent')) { + // program join API call it will increment the noOfResourcesStarted counter and will make user join program + // before creating any project this api has to called + let programUsers = await programUsersQueries.programUsersDocument( + { + userId : userId, + programId : solutionDetails.programId + }, + [ + "_id", + "resourcesStarted" + ] ); - if ( !joinProgramData.success ) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - }); + + if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { + let programJoinBody = {}; + programJoinBody.userRoleInformation = bodyData; + programJoinBody.isResource = true; + let joinProgramData = await coreService.joinProgram ( + solutionDetails.programId, + programJoinBody, + userToken + ); + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); + } } } + let projectCreation = await this.userAssignedProjectCreation( solutionDetails.projectTemplateId, From e105da4d5550fe7ac220bd0935c2e2f7e99a44f5 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 9 May 2023 17:21:15 +0530 Subject: [PATCH 291/373] code formatted --- module/userProjects/helper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 9ceb9a24..5129dcbf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1123,6 +1123,7 @@ module.exports = class UserProjectsHelper { // if requestForPIIConsent not there programDetails will be an empty array if ( programDetails.length > 0 && programDetails[0].hasOwnProperty('requestForPIIConsent')) { + // program join API call it will increment the noOfResourcesStarted counter and will make user join program // before creating any project this api has to called let programUsers = await programUsersQueries.programUsersDocument( From 23e29b3e745c57a26d588c05d1e754a45a9c442a Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 9 May 2023 17:56:07 +0530 Subject: [PATCH 292/373] comments added --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 5129dcbf..12fb06a1 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1121,7 +1121,7 @@ module.exports = class UserProjectsHelper { queryData["_id"] = solutionDetails.programId; let programDetails = await programsQueries.programsDocument(queryData,["requestForPIIConsent"]); - // if requestForPIIConsent not there programDetails will be an empty array + // if requestForPIIConsent not there do not call program join if ( programDetails.length > 0 && programDetails[0].hasOwnProperty('requestForPIIConsent')) { // program join API call it will increment the noOfResourcesStarted counter and will make user join program From 9bc220696765c513759b2c5ab1cce27b3923c83e Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 19 May 2023 16:31:16 +0530 Subject: [PATCH 293/373] passing consentShared = true for internal calls --- models/programUsers.js | 6 +++++- module/userProjects/helper.js | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/models/programUsers.js b/models/programUsers.js index 58b00a3e..b276a3b8 100644 --- a/models/programUsers.js +++ b/models/programUsers.js @@ -21,7 +21,11 @@ module.exports = { required: true }, userRoleInformation: Object, - appInformation: Object + appInformation: Object, + consentShared: { + type: Boolean, + default: false + } }, compoundIndex: [ { diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 12fb06a1..0184647d 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1141,6 +1141,7 @@ module.exports = class UserProjectsHelper { let programJoinBody = {}; programJoinBody.userRoleInformation = bodyData; programJoinBody.isResource = true; + programJoinBody.consentShared = true; let joinProgramData = await coreService.joinProgram ( solutionDetails.programId, programJoinBody, From a3985daa9b8c82a7d869fa04dff1cc5dbc45b5e7 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 22 May 2023 11:42:25 +0530 Subject: [PATCH 294/373] change added to pass userRoleInformation instead entire body data --- module/userProjects/helper.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 0184647d..7400491b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1045,7 +1045,7 @@ module.exports = class UserProjectsHelper { static detailsV2( projectId,solutionId,userId,userToken,bodyData,appName = "",appVersion = "",templateId = "" ) { return new Promise(async (resolve, reject) => { try { - + let solutionExternalId = ""; if( templateId !== "" ) { @@ -1067,11 +1067,12 @@ module.exports = class UserProjectsHelper { solutionId = templateDocuments[0].solutionId; solutionExternalId = templateDocuments[0].solutionExternalId; } - + let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); + if (projectId === "") { // This will check wether the user user is targeted to solution or not based on his userRoleInformation - const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,bodyData,solutionId) + const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,userRoleInformation,solutionId) //based on above api will check for projects wether its is private project or public project const projectDetails = await projectQueries.projectDocument({ solutionId: solutionId, @@ -1139,7 +1140,7 @@ module.exports = class UserProjectsHelper { if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { let programJoinBody = {}; - programJoinBody.userRoleInformation = bodyData; + programJoinBody.userRoleInformation = userRoleInformation; programJoinBody.isResource = true; programJoinBody.consentShared = true; let joinProgramData = await coreService.joinProgram ( From d7c4d09a3d9fc62543b9e3ea8d263347a4f6d247 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 29 May 2023 11:45:44 +0530 Subject: [PATCH 295/373] Bug Fix: ProjectId is not getting passed fixed in dev and staging --- module/project/templates/helper.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index cff8689c..c3faa191 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -1083,10 +1083,9 @@ module.exports = class ProjectTemplatesHelper { if( isAPrivateProgram !== ""){ projectIdQuery.isAPrivateProgram = isAPrivateProgram } - - let project = await projectQueries.projectDocument({ + let project = await projectQueries.projectDocument( projectIdQuery - },["_id"]); + ,["_id"]); if(project && project.length > 0){ templateData[0].projectId = project[0]._id; From 54b1d556288ef6d4119924afe111e2264d7b272c Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 2 Jun 2023 12:30:31 +0530 Subject: [PATCH 296/373] Bug fix catching error if no entity data found --- generics/services/survey.js | 3 ++- module/userProjects/helper.js | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/generics/services/survey.js b/generics/services/survey.js index e15f5c07..bb2f1011 100644 --- a/generics/services/survey.js +++ b/generics/services/survey.js @@ -727,7 +727,8 @@ const listEntitiesByLocationIds = function ( token,locationIds ) { let response = data.body; - if( response.status === HTTP_STATUS_CODE['ok'].status ) { + + if( response.status === HTTP_STATUS_CODE['ok'].status && response.result ) { result["data"] = response.result; } else { result.success = false; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 7400491b..5fa4c8ea 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1259,7 +1259,10 @@ module.exports = class UserProjectsHelper { ); if( !entityInformation.success ) { - return resolve(entityInformation); + throw { + message : CONSTANTS.apiResponses.ENTITY_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } } let entityDetails = await _entitiesMetaInformation( From d463923cb3b98e76f38212f4cd7a5554e32b7e7e Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 16 Jun 2023 14:27:01 +0530 Subject: [PATCH 297/373] Change to create project from private solution --- generics/services/core.js | 6 +++--- module/userProjects/helper.js | 16 ++++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index 7090f3c4..36edd6f5 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -676,15 +676,15 @@ const solutionBasedOnRoleAndLocation = function ( token,bodyData,typeAndSubType, * @param {String} token - User token. * @param {Object} bodyData - Requested body data. * @param {String} solutionId - Targeted solution id. + * @param {Boolean} isAPrivateSolution - true/false. * @returns {JSON} - List of user targetted solutions. */ -const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solutionId ) { +const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solutionId,isAPrivateSolution = false ) { return new Promise(async (resolve, reject) => { try { - const url = - ML_CORE_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId; + ML_CORE_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId + "?isAPrivateSolution=" + isAPrivateSolution; const options = { headers : { diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 5fa4c8ea..f0992c79 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1068,7 +1068,7 @@ module.exports = class UserProjectsHelper { solutionExternalId = templateDocuments[0].solutionExternalId; } - let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); + let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); if (projectId === "") { // This will check wether the user user is targeted to solution or not based on his userRoleInformation @@ -1082,7 +1082,7 @@ module.exports = class UserProjectsHelper { if( projectDetails.length > 0 ) { projectId = projectDetails[0]._id; } else { - + let isAPrivateSolution = (targetedSolutionId.data.isATargetedSolution === false) ? true : false; let solutionDetails = {} if( templateId === "" ) { @@ -1091,7 +1091,8 @@ module.exports = class UserProjectsHelper { await coreService.solutionDetailsBasedOnRoleAndLocation( userToken, bodyData, - solutionId + solutionId, + isAPrivateSolution ); if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { @@ -1167,7 +1168,7 @@ module.exports = class UserProjectsHelper { if( !projectCreation.success ) { return resolve(projectCreation); } - + projectCreation.data["isAPrivateProgram"] = solutionDetails.isAPrivateProgram; @@ -1236,6 +1237,10 @@ module.exports = class UserProjectsHelper { if( bodyData.referenceFrom ) { projectCreation.data.referenceFrom = bodyData.referenceFrom; + // Add link to project Details + if( bodyData.referenceFrom == CONSTANTS.common.LINK && bodyData.link && bodyData.link != "" ) { + projectCreation.data.link = bodyData.link; + } if( bodyData.submissions ) { if ( bodyData.submissions.observationId && bodyData.submissions.observationId != "" ) { @@ -1334,7 +1339,7 @@ module.exports = class UserProjectsHelper { addReportInfoToSolution = true; } } - + projectCreation.data.userRoleInformation = userRoleInformation; //compare & update userProfile with userRoleInformation @@ -2156,7 +2161,6 @@ module.exports = class UserProjectsHelper { static list( bodyData ) { return new Promise(async (resolve, reject) => { try { - let projects = await projectQueries.projectDocument( bodyData.query, bodyData.projection, From 65f4e87ece8ed22429fd40ee1839644bbf159262 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 16 Jun 2023 16:25:23 +0530 Subject: [PATCH 298/373] added release note --- release-notes/6.0.0.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 release-notes/6.0.0.md diff --git a/release-notes/6.0.0.md b/release-notes/6.0.0.md new file mode 100644 index 00000000..2b11342b --- /dev/null +++ b/release-notes/6.0.0.md @@ -0,0 +1,19 @@ +# Release Note 6.0.0 ML projects Service + +This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML projects service code to 6.0.0. Please consider the following list of tasks to be completed. + + +### Deploy ml-projects-services + +To retrieve the latest release tag for version 6.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-6.0.0_RC3 + + +To proceed with the deployment process, follow the steps below: + + 1. Log in to Jenkins. + 2. Navigate to Dashboard -> AutoBuild -> StagingManual -> managed-learn -> ml-projects-service. OR for dev Navigate to Dashboard -> Build -> managed-learn -> ml-projects-service + 3. Click on "Build with parameters" and provide the latest release tag in the field labeled "github_release_tag". Initiate the build process. + 4. The build job will take approximately 5 minutes to complete. + 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-projects-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-projects-service This job will be executed automatically in the dev environment. If not, then it should be built manually. + 6. Click on "Build with parameters" to initiate the deployment process. + 7. Once the job is completed, the services will be deployed on the staging environment From 47eec2310ac81e30c2f8cb97723540c130d2777c Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 16 Jun 2023 16:26:09 +0530 Subject: [PATCH 299/373] added release note --- release-notes/6.0.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/6.0.0.md b/release-notes/6.0.0.md index 2b11342b..bd1ab572 100644 --- a/release-notes/6.0.0.md +++ b/release-notes/6.0.0.md @@ -1,6 +1,6 @@ # Release Note 6.0.0 ML projects Service -This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML projects service code to 6.0.0. Please consider the following list of tasks to be completed. +This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Projects service code to 6.0.0. Please consider the following list of tasks to be completed. ### Deploy ml-projects-services From dc97d5a0237a10f7cf660f84645daf8e29a4f698 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Fri, 16 Jun 2023 16:31:52 +0530 Subject: [PATCH 300/373] solution model updated --- models/solutions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/solutions.js b/models/solutions.js index 536c67c3..2752d2c2 100644 --- a/models/solutions.js +++ b/models/solutions.js @@ -99,6 +99,7 @@ module.exports = { reportInformation : Object, certificateTemplateId : "ObjectId", rootOrganisations : Array, - createdFor : Array + createdFor : Array, + projectTemplateId : "ObjectId" } }; \ No newline at end of file From 7cdcb6a4d64d5221e8ac23efccb5051376f49dd9 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 19 Jun 2023 17:05:39 +0530 Subject: [PATCH 301/373] review changes --- generics/services/core.js | 5 ++- models/solutions.js | 5 ++- module/userProjects/helper.js | 60 ++++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/generics/services/core.js b/generics/services/core.js index 36edd6f5..8a680f8c 100644 --- a/generics/services/core.js +++ b/generics/services/core.js @@ -676,15 +676,14 @@ const solutionBasedOnRoleAndLocation = function ( token,bodyData,typeAndSubType, * @param {String} token - User token. * @param {Object} bodyData - Requested body data. * @param {String} solutionId - Targeted solution id. - * @param {Boolean} isAPrivateSolution - true/false. * @returns {JSON} - List of user targetted solutions. */ -const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solutionId,isAPrivateSolution = false ) { +const solutionDetailsBasedOnRoleAndLocation = function ( token,bodyData,solutionId ) { return new Promise(async (resolve, reject) => { try { const url = - ML_CORE_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId + "?isAPrivateSolution=" + isAPrivateSolution; + ML_CORE_URL + CONSTANTS.endpoints.SOLUTION_DETAILS_BASED_ON_ROLE_LOCATION + "/" + solutionId; const options = { headers : { diff --git a/models/solutions.js b/models/solutions.js index 2752d2c2..11163703 100644 --- a/models/solutions.js +++ b/models/solutions.js @@ -100,6 +100,9 @@ module.exports = { certificateTemplateId : "ObjectId", rootOrganisations : Array, createdFor : Array, - projectTemplateId : "ObjectId" + projectTemplateId : { + type : "ObjectId", + index: true + } } }; \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index f0992c79..6f680034 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1086,23 +1086,53 @@ module.exports = class UserProjectsHelper { let solutionDetails = {} if( templateId === "" ) { - - solutionDetails = - await coreService.solutionDetailsBasedOnRoleAndLocation( - userToken, - bodyData, - solutionId, - isAPrivateSolution - ); + // If solution Id of a private program is passed, fetch solution details + if ( isAPrivateSolution && solutionId != "" ) { + solutionDetails = await database.models.solutions + .find({ + _id: solutionId, + isAPrivateProgram: true + }, [ + "name", + "externalId", + "description", + "programId", + "programName", + "programDescription", + "programExternalId", + "isAPrivateProgram", + "projectTemplateId", + "entityType", + "entityTypeId", + "language", + "creator" + ]) + .lean(); + if( !solutionDetails.length > 0 ) { + throw { + status : HTTP_STATUS_CODE["bad_request"].status, + message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND + } + } + solutionDetails = solutionDetails[0]; + } else { + solutionDetails = + await coreService.solutionDetailsBasedOnRoleAndLocation( + userToken, + bodyData, + solutionId, + isAPrivateSolution + ); - if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { - throw { - status : HTTP_STATUS_CODE["bad_request"].status, - message : CONSTANTS.apiResponses.SOLUTION_DOES_NOT_EXISTS_IN_SCOPE + if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { + throw { + status : HTTP_STATUS_CODE["bad_request"].status, + message : CONSTANTS.apiResponses.SOLUTION_DOES_NOT_EXISTS_IN_SCOPE + } } - } - solutionDetails = solutionDetails.data; + solutionDetails = solutionDetails.data; + } } else { @@ -1363,7 +1393,7 @@ module.exports = class UserProjectsHelper { ); } - await kafkaProducersHelper.pushProjectToKafka(project); + // await kafkaProducersHelper.pushProjectToKafka(project); projectId = project._id; } From 5eca4d76cbb31dfb56298d10606fbfe8328b7055 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 19 Jun 2023 19:32:58 +0530 Subject: [PATCH 302/373] Review resolves --- module/solutions/helper.js | 47 +++++++++++++++++++++++++++++++++++ module/userProjects/helper.js | 17 +++++-------- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/module/solutions/helper.js b/module/solutions/helper.js index 5a0c54c7..168f7e60 100644 --- a/module/solutions/helper.js +++ b/module/solutions/helper.js @@ -141,5 +141,52 @@ module.exports = class SolutionsHelper { } }); } + /** + * Solution Data + * @method + * @name solutionDocuments + * @param {Array} [filterQuery = "all"] - solution ids. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} List of solutions. + */ + + static solutionDocuments( + filterQuery = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + + let queryObject = (filterQuery != "all") ? filterQuery : {}; + + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }) + } + + let solutionDocuments = + await database.models.solutions.find( + queryObject, + projection + ).lean(); + + return resolve(solutionDocuments); + + } catch (error) { + return reject(error); + } + }); + } }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6f680034..72bd9f22 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1068,7 +1068,7 @@ module.exports = class UserProjectsHelper { solutionExternalId = templateDocuments[0].solutionExternalId; } - let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); + let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); if (projectId === "") { // This will check wether the user user is targeted to solution or not based on his userRoleInformation @@ -1088,11 +1088,11 @@ module.exports = class UserProjectsHelper { if( templateId === "" ) { // If solution Id of a private program is passed, fetch solution details if ( isAPrivateSolution && solutionId != "" ) { - solutionDetails = await database.models.solutions - .find({ + solutionDetails = await solutionsHelper.solutionDocuments({ _id: solutionId, isAPrivateProgram: true - }, [ + }, + [ "name", "externalId", "description", @@ -1106,8 +1106,7 @@ module.exports = class UserProjectsHelper { "entityTypeId", "language", "creator" - ]) - .lean(); + ]); if( !solutionDetails.length > 0 ) { throw { status : HTTP_STATUS_CODE["bad_request"].status, @@ -1267,10 +1266,6 @@ module.exports = class UserProjectsHelper { if( bodyData.referenceFrom ) { projectCreation.data.referenceFrom = bodyData.referenceFrom; - // Add link to project Details - if( bodyData.referenceFrom == CONSTANTS.common.LINK && bodyData.link && bodyData.link != "" ) { - projectCreation.data.link = bodyData.link; - } if( bodyData.submissions ) { if ( bodyData.submissions.observationId && bodyData.submissions.observationId != "" ) { @@ -1393,7 +1388,7 @@ module.exports = class UserProjectsHelper { ); } - // await kafkaProducersHelper.pushProjectToKafka(project); + await kafkaProducersHelper.pushProjectToKafka(project); projectId = project._id; } From f9feb033ed5fc8a52d527905a4ef4d3614dd54fc Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 28 Jun 2023 09:30:24 +0530 Subject: [PATCH 303/373] added hasAcceptedTandC in project template details api from project collection --- module/project/templates/helper.js | 2529 ++++++++++++++-------------- 1 file changed, 1275 insertions(+), 1254 deletions(-) diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index c3faa191..588db9ed 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -6,1236 +6,1254 @@ */ /** - * ProjectTemplatesHelper - * @class -*/ + * ProjectTemplatesHelper + * @class + */ // Dependencies -const libraryCategoriesHelper = require(MODULES_BASE_PATH + "/library/categories/helper"); +const libraryCategoriesHelper = require(MODULES_BASE_PATH + + "/library/categories/helper"); const coreService = require(GENERICS_FILES_PATH + "/services/core"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); -const learningResourcesHelper = require(MODULES_BASE_PATH + "/learningResources/helper"); +const learningResourcesHelper = require(MODULES_BASE_PATH + + "/learningResources/helper"); const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); -const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); -const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); +const projectTemplateQueries = require(DB_QUERY_BASE_PATH + + "/projectTemplates"); +const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + + "/projectTemplateTask"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); -const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); +const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + + "/projectCategories"); const solutionsQueries = require(DB_QUERY_BASE_PATH + "/solutions"); -const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); +const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + + "/certificateTemplates"); module.exports = class ProjectTemplatesHelper { + /** + * Extract csv information. + * @method + * @name extractCsvInformation + * @param {Object} csvData - csv data. + * @returns {Object} Extra csv information. + */ + + static extractCsvInformation(csvData) { + return new Promise(async (resolve, reject) => { + try { + let categoryIds = []; + let roleIds = []; + let tasksIds = []; + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // let entityTypes = []; + + csvData.forEach((template) => { + let parsedData = UTILS.valueParser(template); + + categoryIds = _.concat(categoryIds, parsedData.categories); + + tasksIds = _.concat(tasksIds, parsedData.tasks); + + if (parsedData.recommendedFor) { + parsedData.recommendedFor = parsedData.recommendedFor.map( + (role) => { + return role.toUpperCase(); + } + ); + + roleIds = _.concat(roleIds, parsedData.recommendedFor); + } + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // if( parsedData.entityType ) { + // entityTypes.push(parsedData.entityType); + // } + }); + + let categoriesData = {}; + + if (categoryIds.length > 0) { + let categories = await projectCategoriesQueries.categoryDocuments( + { + externalId: { $in: categoryIds }, + }, + ["externalId", "name"] + ); + + if (!categories.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.LIBRARY_CATEGORIES_NOT_FOUND, + }; + } + + categoriesData = categories.reduce( + (ac, category) => ({ + ...ac, + [category.externalId]: { + _id: ObjectId(category._id), + externalId: category.externalId, + name: category.name, + }, + }), + {} + ); + } - /** - * Extract csv information. - * @method - * @name extractCsvInformation - * @param {Object} csvData - csv data. - * @returns {Object} Extra csv information. - */ - - static extractCsvInformation(csvData) { - return new Promise(async (resolve, reject) => { - try { - - let categoryIds = []; - let roleIds = []; - let tasksIds = []; - // <- Entitytype validation removed {release-5.0.0} - entity generalisation - // let entityTypes = []; - - csvData.forEach(template=>{ - - let parsedData = UTILS.valueParser(template); - - categoryIds = _.concat( - categoryIds, - parsedData.categories - ); + let recommendedFor = {}; + + if (roleIds.length > 0) { + let userRolesData = await coreService.rolesDocuments( + { + code: { $in: roleIds }, + }, + ["code"] + ); + + if (!userRolesData.success) { + throw { + message: CONSTANTS.apiResponses.USER_ROLES_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } + + recommendedFor = userRolesData.data.reduce( + (ac, role) => ({ + ...ac, + [role.code]: { + roleId: ObjectId(role._id), + code: role.code, + }, + }), + {} + ); + } + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // let entityTypesData = {}; + + // if( entityTypes.length > 0 ) { + + // let entityTypesDocument = + // await coreService.entityTypesDocuments(); + + // if( !entityTypesDocument.success ) { + // throw { + // message : CONSTANTS.apiResponses.ENTITY_TYPES_NOT_FOUND, + // status : HTTP_STATUS_CODE['bad_request'].status + // } + // } + + // entityTypesData = entityTypesDocument.data.reduce((ac,entityType)=> ({ + // ...ac, + // [entityType.name] : { + // _id : ObjectId(entityType._id), + // name : entityType.name + // } + // }),{}); + + // } + + return resolve({ + success: true, + data: { + categories: categoriesData, + roles: recommendedFor, + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // entityTypes : entityTypesData + }, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); + } + + /** + * Template data. + * @method + * @name templateData + * @param {Object} data - csv data. + * @param {Object} csvInformation - csv information. + * @returns {Object} Template data. + */ + + static templateData(data, csvInformation) { + return new Promise(async (resolve, reject) => { + try { + let templatesDataModel = Object.keys( + schemas["project-templates"].schema + ); + let parsedData = UTILS.valueParser(data); + delete parsedData._arrayFields; + + let categories = []; + + if (parsedData.categories && parsedData.categories.length > 0) { + parsedData.categories.forEach((category) => { + if (csvInformation.categories[category]) { + return categories.push(csvInformation.categories[category]); + } + }); + } - tasksIds = _.concat( - tasksIds, - parsedData.tasks - ); + parsedData.categories = categories; - if( parsedData.recommendedFor ) { - - parsedData.recommendedFor = - parsedData.recommendedFor.map(role=>{ - return role.toUpperCase() - }); - - roleIds = _.concat( - roleIds, - parsedData.recommendedFor - ); - } - // <- Entitytype validation removed {release-5.0.0} - entity generalisation - // if( parsedData.entityType ) { - // entityTypes.push(parsedData.entityType); - // } + let recommendedFor = []; - }); + if (parsedData.recommendedFor && parsedData.recommendedFor.length > 0) { + parsedData.recommendedFor.forEach((recommended) => { + if (csvInformation.roles[recommended]) { + return recommendedFor.push(csvInformation.roles[recommended]); + } + }); + } - let categoriesData = {}; - - if( categoryIds.length > 0 ) { - - let categories = - await projectCategoriesQueries.categoryDocuments({ - externalId : { $in : categoryIds } - },["externalId","name"]); - - if( !categories.length > 0 ) { - throw { - status : HTTP_STATUS_CODE['bad_request'].status, - message : CONSTANTS.apiResponses.LIBRARY_CATEGORIES_NOT_FOUND - } - } - - categoriesData = categories.reduce((ac,category)=> ({ - ...ac, - [category.externalId] : { - _id : ObjectId(category._id), - externalId : category.externalId, - name : category.name - } - }),{}); - } + parsedData.recommendedFor = recommendedFor; + // <- Entitytype validation removed {release-5.0.0} - entity generalisation + // if( parsedData.entityType && parsedData.entityType !== "" ) { + // parsedData.entityType = csvInformation.entityTypes[parsedData.entityType].name; + // } + + let learningResources = + await learningResourcesHelper.extractLearningResourcesFromCsv( + parsedData + ); + parsedData.learningResources = learningResources.data; + + parsedData.metaInformation = {}; + let booleanData = UTILS.getAllBooleanDataFromModels( + schemas["project-templates"].schema + ); + + Object.keys(parsedData).forEach((eachParsedData) => { + if (!templatesDataModel.includes(eachParsedData)) { + if (!eachParsedData.startsWith("learningResources")) { + parsedData.metaInformation[eachParsedData] = + parsedData[eachParsedData]; + delete parsedData[eachParsedData]; + } + } else { + if (booleanData.includes(eachParsedData)) { + parsedData[eachParsedData] = UTILS.convertStringToBoolean( + parsedData[eachParsedData] + ); + } + } + }); - let recommendedFor = {}; - - if( roleIds.length > 0 ) { - - let userRolesData = - await coreService.rolesDocuments({ - code : { $in : roleIds } - },["code"]); - - if( !userRolesData.success ) { - throw { - message : CONSTANTS.apiResponses.USER_ROLES_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - recommendedFor = userRolesData.data.reduce((ac,role)=> ({ - ...ac, - [role.code] : { - roleId : ObjectId(role._id), - code : role.code - } - }),{}); - } - // <- Entitytype validation removed {release-5.0.0} - entity generalisation - // let entityTypesData = {}; - - // if( entityTypes.length > 0 ) { - - // let entityTypesDocument = - // await coreService.entityTypesDocuments(); - - // if( !entityTypesDocument.success ) { - // throw { - // message : CONSTANTS.apiResponses.ENTITY_TYPES_NOT_FOUND, - // status : HTTP_STATUS_CODE['bad_request'].status - // } - // } - - // entityTypesData = entityTypesDocument.data.reduce((ac,entityType)=> ({ - // ...ac, - // [entityType.name] : { - // _id : ObjectId(entityType._id), - // name : entityType.name - // } - // }),{}); - - // } - - return resolve({ - success : true, - data : { - categories : categoriesData, - roles : recommendedFor, - // <- Entitytype validation removed {release-5.0.0} - entity generalisation - // entityTypes : entityTypesData - } - }); + parsedData.isReusable = true; + + return resolve(parsedData); + } catch (error) { + return reject(error); + } + }); + } + + /** + * Bulk created project templates. + * @method + * @name bulkCreate - bulk create project templates. + * @param {Array} templates - csv templates data. + * @param {String} userId - logged in user id. + * @returns {Object} Bulk create project templates. + */ + + static bulkCreate(templates, userId) { + return new Promise(async (resolve, reject) => { + try { + const fileName = `project-templates-creation`; + let fileStream = new CSV_FILE_STREAM(fileName); + let input = fileStream.initStream(); + + (async function () { + await fileStream.getProcessorPromise(); + return resolve({ + isResponseAStream: true, + fileNameWithPath: fileStream.fileNameWithPath(), + }); + })(); + + let csvInformation = await this.extractCsvInformation(templates); + + if (!csvInformation.success) { + return resolve(csvInformation); + } - } catch(error) { - return resolve({ - success : false, - message : error.message, - status : error.status ? error.status : HTTP_STATUS_CODE['internal_server_error'].status + for (let template = 0; template < templates.length; template++) { + let currentData = templates[template]; + + let templateData = await projectTemplateQueries.templateDocument( + { + status: CONSTANTS.common.PUBLISHED, + externalId: currentData.externalId, + isReusable: true, + }, + ["_id"] + ); + + if (templateData.length > 0 && templateData[0]._id) { + currentData["_SYSTEM_ID"] = + CONSTANTS.apiResponses.PROJECT_TEMPLATE_EXISTS; + } else { + let templateData = await this.templateData( + currentData, + csvInformation.data, + userId + ); + + templateData.status = CONSTANTS.common.PUBLISHED_STATUS; + templateData.createdBy = + templateData.updatedBy = + templateData.userId = + userId; + templateData.isReusable = true; + + let createdTemplate = await projectTemplateQueries.createTemplate( + templateData + ); + + if (!createdTemplate._id) { + currentData["_SYSTEM_ID"] = + CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; + } else { + currentData["_SYSTEM_ID"] = createdTemplate._id; + + if ( + templateData.categories && + templateData.categories.length > 0 + ) { + let categories = templateData.categories.map((category) => { + return category._id; }); - } - }) - } - /** - * Template data. - * @method - * @name templateData - * @param {Object} data - csv data. - * @param {Object} csvInformation - csv information. - * @returns {Object} Template data. - */ - - static templateData(data,csvInformation) { - return new Promise(async (resolve, reject) => { - try { - - let templatesDataModel = - Object.keys(schemas["project-templates"].schema); - let parsedData = UTILS.valueParser(data); - delete parsedData._arrayFields; - - let categories = []; - - if( parsedData.categories && parsedData.categories.length > 0 ) { - - parsedData.categories.forEach( category => { - if( csvInformation.categories[category] ) { - return categories.push( - csvInformation.categories[category] - ); - } - }); - } + let updatedCategories = await libraryCategoriesHelper.update( + { + _id: { $in: categories }, + }, + { + $inc: { noOfProjects: 1 }, + } + ); - parsedData.categories = categories; - - let recommendedFor = []; - - if( parsedData.recommendedFor && parsedData.recommendedFor.length > 0 ) { - parsedData.recommendedFor.forEach(recommended => { - if( csvInformation.roles[recommended] ) { - return recommendedFor.push( - csvInformation.roles[recommended] - ); - } - }); + if (!updatedCategories.success) { + currentData["_SYSTEM_ID"] = updatedCategories.message; } + } + + // <- Dirty fix . Not required + // const kafkaMessage = + // await kafkaProducersHelper.pushProjectToKafka({ + // internal : false, + // text : + // templateData.categories.length === 1 ? + // `A new project has been added under ${templateData.categories[0].name} category in library.` : + // `A new project has been added in library`, + // type : "information", + // action : "mapping", + // payload : { + // project_id: createdTemplate._id + // }, + // is_read : false, + // internal : false, + // title : "New project Available!", + // created_at : new Date(), + // appType : process.env.IMPROVEMENT_PROJECT_APP_TYPE, + // inApp:false, + // push: true, + // pushToTopic: true, + // topicName : process.env.NODE_ENV + "-" + process.env.IMPROVEMENT_PROJECT_APP_NAME + process.env.TOPIC_FOR_ALL_USERS + // }); + + // if (kafkaMessage.status !== CONSTANTS.common.SUCCESS) { + // currentData["_SYSTEM_ID"] = CONSTANTS.apiResponses.COULD_NOT_PUSHED_TO_KAFKA; + // } + } + } - parsedData.recommendedFor = recommendedFor; - // <- Entitytype validation removed {release-5.0.0} - entity generalisation - // if( parsedData.entityType && parsedData.entityType !== "" ) { - // parsedData.entityType = csvInformation.entityTypes[parsedData.entityType].name; - // } + input.push(currentData); + } - let learningResources = - await learningResourcesHelper.extractLearningResourcesFromCsv(parsedData); - parsedData.learningResources = learningResources.data; + input.push(null); + } catch (error) { + return reject(error); + } + }); + } + + /** + * Bulk update project templates. + * @method + * @name bulkUpdate - bulk update project templates. + * @param {Array} templates - csv templates data. + * @param {String} userId - logged in user id. + * @returns {Object} Bulk Update Project templates. + */ + + static bulkUpdate(templates, userId) { + return new Promise(async (resolve, reject) => { + try { + const fileName = `project-templates-updation`; + let fileStream = new CSV_FILE_STREAM(fileName); + let input = fileStream.initStream(); + + (async function () { + await fileStream.getProcessorPromise(); + return resolve({ + isResponseAStream: true, + fileNameWithPath: fileStream.fileNameWithPath(), + }); + })(); + + let csvInformation = await this.extractCsvInformation(templates); + + if (!csvInformation.success) { + return resolve(csvInformation); + } - parsedData.metaInformation = {}; - let booleanData = - UTILS.getAllBooleanDataFromModels( - schemas["project-templates"].schema + for (let template = 0; template < templates.length; template++) { + const currentData = templates[template]; + + if (!currentData._SYSTEM_ID) { + currentData["UPDATE_STATUS"] = + CONSTANTS.apiResponses.MISSING_PROJECT_TEMPLATE_ID; + } else { + const template = await projectTemplateQueries.templateDocument( + { + status: CONSTANTS.common.PUBLISHED, + _id: currentData._SYSTEM_ID, + status: CONSTANTS.common.PUBLISHED, + }, + ["_id", "categories", "isReusable"] + ); + + if (!(template.length > 0 && template[0]._id)) { + currentData["UPDATE_STATUS"] = + CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; + } else { + let templateData = await this.templateData( + _.omit(currentData, ["_SYSTEM_ID"]), + csvInformation.data, + userId + ); + + if (template[0].isReusable === false) { + templateData.isReusable = false; + } + + templateData.updatedBy = userId; + + let projectTemplateUpdated = + await projectTemplateQueries.findOneAndUpdate( + { + _id: currentData._SYSTEM_ID, + }, + { + $set: templateData, + }, + { + new: true, + } ); - Object.keys(parsedData).forEach( eachParsedData => { - if( - !templatesDataModel.includes(eachParsedData) - ) { - - if( !eachParsedData.startsWith("learningResources") ) { - parsedData.metaInformation[eachParsedData] = - parsedData[eachParsedData]; - delete parsedData[eachParsedData]; - } - - } else { - if( booleanData.includes(eachParsedData) ) { - parsedData[eachParsedData] = - UTILS.convertStringToBoolean(parsedData[eachParsedData]); - } - } + if (!projectTemplateUpdated || !projectTemplateUpdated._id) { + currentData["UPDATE_STATUS"] = + CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED; + } + + // Add projects count to categories + if ( + templateData.categories && + templateData.categories.length > 0 + ) { + let categories = templateData.categories.map((category) => { + return category._id; }); - parsedData.isReusable = true; - - return resolve(parsedData); + let updatedCategories = await libraryCategoriesHelper.update( + { + _id: { $in: categories }, + }, + { + $inc: { noOfProjects: 1 }, + } + ); - } catch(error) { - return reject(error); - } - }) - } + if (!updatedCategories.success) { + currentData["UPDATE_STATUS"] = updatedCategories.message; + } + } - /** - * Bulk created project templates. - * @method - * @name bulkCreate - bulk create project templates. - * @param {Array} templates - csv templates data. - * @param {String} userId - logged in user id. - * @returns {Object} Bulk create project templates. - */ - - static bulkCreate(templates,userId) { - - return new Promise(async (resolve, reject) => { - - try { - - const fileName = `project-templates-creation`; - let fileStream = new CSV_FILE_STREAM(fileName); - let input = fileStream.initStream(); - - (async function () { - await fileStream.getProcessorPromise(); - return resolve({ - isResponseAStream: true, - fileNameWithPath: fileStream.fileNameWithPath() - }); - })(); + // Remove project count from existing categories + if (template[0].categories && template[0].categories.length > 0) { + const categoriesIds = template[0].categories.map((category) => { + return category._id; + }); - let csvInformation = await this.extractCsvInformation(templates); + let categoriesUpdated = await libraryCategoriesHelper.update( + { + _id: { $in: categoriesIds }, + }, + { + $inc: { noOfProjects: -1 }, + } + ); - if( !csvInformation.success ) { - return resolve(csvInformation); + if (!categoriesUpdated.success) { + currentData["UPDATE_STATUS"] = updatedCategories.message; } + } - for ( let template = 0; template < templates.length ; template ++ ) { - - let currentData = templates[template]; - - let templateData = - await projectTemplateQueries.templateDocument({ - status : CONSTANTS.common.PUBLISHED, - externalId : currentData.externalId, - isReusable : true - },["_id"]); - - if( templateData.length > 0 && templateData[0]._id ) { - currentData["_SYSTEM_ID"] = - CONSTANTS.apiResponses.PROJECT_TEMPLATE_EXISTS; - } else { - - let templateData = await this.templateData( - currentData, - csvInformation.data, - userId - ); - - templateData.status = CONSTANTS.common.PUBLISHED_STATUS; - templateData.createdBy = templateData.updatedBy = templateData.userId = userId; - templateData.isReusable = true; - - let createdTemplate = await projectTemplateQueries.createTemplate(templateData); - - if( !createdTemplate._id ) { - currentData["_SYSTEM_ID"] = CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; - } else { - - currentData["_SYSTEM_ID"] = createdTemplate._id; - - if( - templateData.categories && - templateData.categories.length > 0 - ) { - - let categories = templateData.categories.map(category => { - return category._id; - }); - - let updatedCategories = - await libraryCategoriesHelper.update({ - _id : { $in : categories } - },{ - $inc : { noOfProjects : 1 } - }); - - if( !updatedCategories.success ) { - currentData["_SYSTEM_ID"] = updatedCategories.message; - } - } - - // <- Dirty fix . Not required - // const kafkaMessage = - // await kafkaProducersHelper.pushProjectToKafka({ - // internal : false, - // text : - // templateData.categories.length === 1 ? - // `A new project has been added under ${templateData.categories[0].name} category in library.` : - // `A new project has been added in library`, - // type : "information", - // action : "mapping", - // payload : { - // project_id: createdTemplate._id - // }, - // is_read : false, - // internal : false, - // title : "New project Available!", - // created_at : new Date(), - // appType : process.env.IMPROVEMENT_PROJECT_APP_TYPE, - // inApp:false, - // push: true, - // pushToTopic: true, - // topicName : process.env.NODE_ENV + "-" + process.env.IMPROVEMENT_PROJECT_APP_NAME + process.env.TOPIC_FOR_ALL_USERS - // }); - - // if (kafkaMessage.status !== CONSTANTS.common.SUCCESS) { - // currentData["_SYSTEM_ID"] = CONSTANTS.apiResponses.COULD_NOT_PUSHED_TO_KAFKA; - // } - - } - - } - - input.push(currentData); + currentData["UPDATE_STATUS"] = CONSTANTS.common.SUCCESS; + } + } - } + input.push(templates[template]); + } - input.push(null); + input.push(null); + } catch (error) { + return reject(error); + } + }); + } + + /** + * Bulk update project templates. + * @method + * @name importProjectTemplate - import templates from existing project templates. + * @param {String} templateId - project template id. + * @param {String} userId - logged in user id. + * @param {String} userToken - logged in user token. + * @param {String} solutionId - solution id. + * @param {Object} updateData - template update data. + * @returns {Object} imported templates data. + */ + + static importProjectTemplate( + templateId, + userId, + userToken, + solutionId, + updateData = {} + ) { + return new Promise(async (resolve, reject) => { + try { + let projectTemplateData = await projectTemplateQueries.templateDocument( + { + status: CONSTANTS.common.PUBLISHED, + externalId: templateId, + isReusable: true, + } + ); + + if (!projectTemplateData.length > 0) { + throw new Error(CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND); + } - } catch (error) { - return reject(error); - } - }) - } + let newProjectTemplate = { ...projectTemplateData[0] }; + newProjectTemplate.externalId = + projectTemplateData[0].externalId + "-" + UTILS.epochTime(); + newProjectTemplate.createdBy = newProjectTemplate.updatedBy = userId; - /** - * Bulk update project templates. - * @method - * @name bulkUpdate - bulk update project templates. - * @param {Array} templates - csv templates data. - * @param {String} userId - logged in user id. - * @returns {Object} Bulk Update Project templates. - */ - - static bulkUpdate(templates,userId) { - return new Promise(async (resolve, reject) => { - try { - - const fileName = `project-templates-updation`; - let fileStream = new CSV_FILE_STREAM(fileName); - let input = fileStream.initStream(); - - (async function () { - await fileStream.getProcessorPromise(); - return resolve({ - isResponseAStream: true, - fileNameWithPath: fileStream.fileNameWithPath() - }); - })(); + let solutionData = await surveyService.listSolutions([solutionId]); - let csvInformation = await this.extractCsvInformation(templates); + if (!solutionData.success) { + throw { + message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - if( !csvInformation.success ) { - return resolve(csvInformation); - } + if ( + solutionData.data[0].type !== CONSTANTS.common.IMPROVEMENT_PROJECT + ) { + throw { + message: + CONSTANTS.apiResponses.IMPROVEMENT_PROJECT_SOLUTION_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - for ( let template = 0; template < templates.length ; template ++ ) { - - const currentData = templates[template]; - - if ( !currentData._SYSTEM_ID ) { - currentData["UPDATE_STATUS"] = - CONSTANTS.apiResponses.MISSING_PROJECT_TEMPLATE_ID; - } else { - - const template = - await projectTemplateQueries.templateDocument({ - status : CONSTANTS.common.PUBLISHED, - _id : currentData._SYSTEM_ID, - status : CONSTANTS.common.PUBLISHED - },["_id","categories", "isReusable"]); - - if ( !(template.length > 0 && template[0]._id) ) { - currentData["UPDATE_STATUS"] = - CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND; - } else { - - let templateData = await this.templateData( - _.omit(currentData,["_SYSTEM_ID"]), - csvInformation.data, - userId - ); - - if(template[0].isReusable === false) { - templateData.isReusable = false; - } - - templateData.updatedBy = userId; - - let projectTemplateUpdated = - await projectTemplateQueries.findOneAndUpdate({ - _id : currentData._SYSTEM_ID - },{ - $set : templateData - },{ - new : true - }); - - if( !projectTemplateUpdated || !projectTemplateUpdated._id ) { - currentData["UPDATE_STATUS"] = - CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED; - } - - // Add projects count to categories - if( - templateData.categories && - templateData.categories.length > 0 - ) { - - let categories = - templateData.categories.map(category => { - return category._id; - }); - - let updatedCategories = - await libraryCategoriesHelper.update({ - _id : { $in : categories } - },{ - $inc : { noOfProjects : 1 } - }); - - if( !updatedCategories.success ) { - currentData["UPDATE_STATUS"] = updatedCategories.message; - } - } - - // Remove project count from existing categories - if( - template[0].categories && - template[0].categories.length > 0 - ) { - - const categoriesIds = - template[0].categories.map(category=>{ - return category._id; - }); - - let categoriesUpdated = - await libraryCategoriesHelper.update({ - _id : { $in : categoriesIds } - },{ - $inc : { noOfProjects : -1 } - }); - - if( !categoriesUpdated.success ) { - currentData["UPDATE_STATUS"] = updatedCategories.message; - } - } - - currentData["UPDATE_STATUS"] = CONSTANTS.common.SUCCESS; - } - - } - - input.push(templates[template]); + if (solutionData.data[0].projectTemplateId) { + throw { + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_EXISTS_IN_SOLUTION, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - } + if ( + projectTemplateData[0].entityType && + projectTemplateData[0].entityType !== "" && + projectTemplateData[0].entityType !== solutionData.data[0].entityType + ) { + throw { + message: CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - input.push(null); + newProjectTemplate.solutionId = solutionData.data[0]._id; + newProjectTemplate.solutionExternalId = solutionData.data[0].externalId; + newProjectTemplate.programId = solutionData.data[0].programId; + newProjectTemplate.programExternalId = + solutionData.data[0].programExternalId; - } catch (error) { - return reject(error); - } - }) - } - - /** - * Bulk update project templates. - * @method - * @name importProjectTemplate - import templates from existing project templates. - * @param {String} templateId - project template id. - * @param {String} userId - logged in user id. - * @param {String} userToken - logged in user token. - * @param {String} solutionId - solution id. - * @param {Object} updateData - template update data. - * @returns {Object} imported templates data. - */ - - static importProjectTemplate( templateId,userId,userToken,solutionId,updateData = {} ) { - return new Promise(async (resolve, reject) => { - try { - - let projectTemplateData = - await projectTemplateQueries.templateDocument({ - status : CONSTANTS.common.PUBLISHED, - externalId : templateId, - isReusable : true - }); - - if ( !projectTemplateData.length > 0 ) { - throw new Error(CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND) - } + newProjectTemplate.parentTemplateId = projectTemplateData[0]._id; - let newProjectTemplate = {...projectTemplateData[0]}; - newProjectTemplate.externalId = - projectTemplateData[0].externalId +"-"+ UTILS.epochTime(); - newProjectTemplate.createdBy = newProjectTemplate.updatedBy = userId; - - let solutionData = - await surveyService.listSolutions([solutionId]); - - if( !solutionData.success ) { - throw { - message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } + let updationKeys = Object.keys(updateData); + if (updationKeys.length > 0) { + updationKeys.forEach((singleKey) => { + if (newProjectTemplate[singleKey]) { + newProjectTemplate[singleKey] = updateData[singleKey]; + } + }); + } - if( solutionData.data[0].type !== CONSTANTS.common.IMPROVEMENT_PROJECT ) { - throw { - message : CONSTANTS.apiResponses.IMPROVEMENT_PROJECT_SOLUTION_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } + let tasksIds; - if( solutionData.data[0].projectTemplateId ) { - throw { - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_EXISTS_IN_SOLUTION, - status : HTTP_STATUS_CODE['bad_request'].status - } - } + if (projectTemplateData[0].tasks) { + tasksIds = projectTemplateData[0].tasks; + } - if( - projectTemplateData[0].entityType && - projectTemplateData[0].entityType !== "" && - projectTemplateData[0].entityType !== solutionData.data[0].entityType - ) { - throw { - message : CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - newProjectTemplate.solutionId = solutionData.data[0]._id; - newProjectTemplate.solutionExternalId = solutionData.data[0].externalId; - newProjectTemplate.programId = solutionData.data[0].programId; - newProjectTemplate.programExternalId = solutionData.data[0].programExternalId; - - - newProjectTemplate.parentTemplateId = projectTemplateData[0]._id; - - let updationKeys = Object.keys(updateData); - if( updationKeys.length > 0 ) { - updationKeys.forEach(singleKey => { - if( newProjectTemplate[singleKey] ) { - newProjectTemplate[singleKey] = updateData[singleKey]; - } - }) - } + newProjectTemplate.isReusable = false; - let tasksIds; - - if(projectTemplateData[0].tasks){ - tasksIds = projectTemplateData[0].tasks; - } + let duplicateTemplateDocument = + await projectTemplateQueries.createTemplate( + _.omit(newProjectTemplate, ["_id"]) + ); - newProjectTemplate.isReusable = false; + if (!duplicateTemplateDocument._id) { + throw new Error(CONSTANTS.apiResponses.PROJECT_TEMPLATES_NOT_CREATED); + } - let duplicateTemplateDocument = - await projectTemplateQueries.createTemplate( - _.omit(newProjectTemplate, ["_id"]) - ); + //duplicate task + if (Array.isArray(tasksIds) && tasksIds.length > 0) { + await this.duplicateTemplateTasks( + tasksIds, + duplicateTemplateDocument._id, + duplicateTemplateDocument.externalId + ); + } - if ( !duplicateTemplateDocument._id ) { - throw new Error(CONSTANTS.apiResponses.PROJECT_TEMPLATES_NOT_CREATED) - } + await surveyService.updateSolution( + userToken, + { + projectTemplateId: duplicateTemplateDocument._id, + name: duplicateTemplateDocument.title, + }, + newProjectTemplate.solutionExternalId + ); + + await this.ratings( + projectTemplateData[0]._id, + updateData.rating, + userToken + ); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.DUPLICATE_PROJECT_TEMPLATES_CREATED, + data: { + _id: duplicateTemplateDocument._id, + }, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); + } + + /** + * Create ratings. + * @method + * @name ratings + * @param {String} templateId - project template id. + * @param {String} rating - rating for template. + * @returns {Object} rating object. + */ + + static ratings(templateId, rating, userToken) { + return new Promise(async (resolve, reject) => { + try { + let userProfileData = await coreService.getProfile(userToken); + + if (!userProfileData.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND, + }; + } - //duplicate task - if(Array.isArray(tasksIds) && tasksIds.length > 0 ){ - await this.duplicateTemplateTasks( - tasksIds, - duplicateTemplateDocument._id, - duplicateTemplateDocument.externalId - ); - } + let templateData = await projectTemplateQueries.templateDocument( + { + status: CONSTANTS.common.PUBLISHED, + _id: templateId, + isReusable: true, + }, + ["averageRating", "noOfRatings", "ratings"] + ); + + let updateRating = { + ratings: { ...templateData[0].ratings }, + }; + + updateRating.ratings[rating] += 1; + + let userCurrentRating = 0; + let projectIndex = -1; + + if ( + userProfileData.data && + userProfileData.data.ratings && + userProfileData.data.ratings.length > 0 + ) { + projectIndex = userProfileData.data.ratings.findIndex( + (project) => project._id.toString() === templateId.toString() + ); + + if (!(projectIndex < 0)) { + userCurrentRating = + userProfileData.data.ratings[projectIndex].rating; + updateRating.ratings[userCurrentRating] -= 1; + } + } else { + userProfileData.data.ratings = []; + } - await surveyService.updateSolution( - userToken, - { - projectTemplateId : duplicateTemplateDocument._id, - name : duplicateTemplateDocument.title - }, - newProjectTemplate.solutionExternalId - ); - - await this.ratings( - projectTemplateData[0]._id, - updateData.rating, - userToken - ); - - return resolve({ - success: true, - message : CONSTANTS.apiResponses.DUPLICATE_PROJECT_TEMPLATES_CREATED, - data : { - _id : duplicateTemplateDocument._id - } - }) - - } catch (error) { - return resolve({ - status : - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); + let ratingUpdated = {}; + + if (userCurrentRating === rating) { + ratingUpdated = templateData[0]; + } else { + let calculateRating = _calculateRating(updateRating.ratings); + updateRating.averageRating = calculateRating.averageRating; + updateRating.noOfRatings = calculateRating.noOfRatings; + + ratingUpdated = await projectTemplateQueries.findOneAndUpdate( + { + _id: templateId, + }, + { + $set: updateRating, + }, + { + new: true, } - }) - } + ); + + let improvementProjects = [...userProfileData.data.ratings]; + if (projectIndex >= 0) { + improvementProjects[projectIndex].rating = rating; + } else { + improvementProjects.push({ + _id: ObjectId(templateId), + externalId: ratingUpdated.externalId, + rating: rating, + type: CONSTANTS.common.IMPROVEMENT_PROJECT, + }); + } - /** - * Create ratings. - * @method - * @name ratings - * @param {String} templateId - project template id. - * @param {String} rating - rating for template. - * @returns {Object} rating object. - */ - - static ratings( templateId,rating,userToken ) { - return new Promise(async (resolve, reject) => { - try { - - let userProfileData = await coreService.getProfile(userToken); - - if( !userProfileData.success ) { - throw { - status : HTTP_STATUS_CODE['bad_request'].status, - message : CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND - } - } + await coreService.updateUserProfile(userToken, { + ratings: improvementProjects, + }); + } - let templateData = - await projectTemplateQueries.templateDocument({ - status : CONSTANTS.common.PUBLISHED, - _id : templateId, - isReusable : true - },[ - "averageRating", - "noOfRatings", - "ratings" - ]); - - let updateRating = { - ratings : {...templateData[0].ratings} - }; - - updateRating.ratings[rating] += 1; - - let userCurrentRating = 0; - let projectIndex = -1; - - if( - userProfileData.data && - userProfileData.data.ratings && - userProfileData.data.ratings.length > 0 + return resolve( + _.pick(ratingUpdated, ["averageRating", "noOfRatings", "ratings"]) + ); + } catch (error) { + return resolve({ + success: false, + message: error.message, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); + } + + /** + * Project template tasks + * @method + * @name duplicateTemplateTasks + * @param {Array} taskIds - Task ids + * @returns {Object} Duplicated tasks. + */ + + static duplicateTemplateTasks( + taskIds = [], + duplicateTemplateId, + duplicateTemplateExternalId + ) { + return new Promise(async (resolve, reject) => { + try { + let newTaskId = []; + + for ( + let pointerToTask = 0; + pointerToTask < taskIds.length; + pointerToTask++ + ) { + let taskId = taskIds[pointerToTask]; + let taskData = await projectTemplateTaskQueries.taskDocuments({ + _id: taskId, + parentId: { $exists: false }, + }); + + if (taskData && taskData.length > 0) { + taskData = taskData[0]; + } + + if (taskData && Object.keys(taskData).length > 0) { + //duplicate parent task + let newProjectTemplateTask = { ...taskData }; + newProjectTemplateTask.projectTemplateId = duplicateTemplateId; + newProjectTemplateTask.projectTemplateExternalId = + duplicateTemplateExternalId; + newProjectTemplateTask.externalId = + taskData.externalId + "-" + UTILS.epochTime(); + + let duplicateTemplateTask = + await database.models.projectTemplateTasks.create( + _.omit(newProjectTemplateTask, ["_id"]) + ); + + newTaskId.push(duplicateTemplateTask._id); + + //duplicate child task + if ( + duplicateTemplateTask.children && + duplicateTemplateTask.children.length > 0 + ) { + let childTaskIdArray = []; + let childTaskIds = duplicateTemplateTask.children; + + if (childTaskIds && childTaskIds.length > 0) { + for ( + let pointerToChild = 0; + pointerToChild < childTaskIds.length; + pointerToChild++ ) { - - projectIndex = - userProfileData.data.ratings.findIndex( - project => project._id.toString() === templateId.toString() - ); - - if( !(projectIndex < 0) ) { - userCurrentRating = userProfileData.data.ratings[projectIndex].rating; - updateRating.ratings[userCurrentRating] -= 1; - } - } else { - userProfileData.data.ratings = []; - } - - let ratingUpdated = {}; - - if( userCurrentRating === rating ) { - - ratingUpdated = templateData[0]; - - } else { - - let calculateRating = _calculateRating(updateRating.ratings); - updateRating.averageRating = calculateRating.averageRating; - updateRating.noOfRatings = calculateRating.noOfRatings; - - ratingUpdated = - await projectTemplateQueries.findOneAndUpdate({ - _id : templateId - },{ - $set : updateRating - }, { - new : true + let childtaskId = childTaskIds[pointerToChild]; + let childTaskData = + await projectTemplateTaskQueries.taskDocuments({ + _id: childtaskId, }); - let improvementProjects = [...userProfileData.data.ratings]; - if( projectIndex >= 0 ) { - improvementProjects[projectIndex].rating = rating; - } else { - improvementProjects.push({ - _id : ObjectId(templateId), - externalId : ratingUpdated.externalId, - rating : rating, - type : CONSTANTS.common.IMPROVEMENT_PROJECT - }); - } - - await coreService.updateUserProfile( - userToken, - { - "ratings" : improvementProjects - } + if (childTaskData && childTaskData.length > 0) { + childTaskData = childTaskData[0]; + } + + if (childTaskData && Object.keys(childTaskData).length > 0) { + let newProjectTemplateChildTask = { ...childTaskData }; + newProjectTemplateChildTask.projectTemplateId = + duplicateTemplateId; + newProjectTemplateChildTask.projectTemplateExternalId = + duplicateTemplateExternalId; + newProjectTemplateChildTask.parentId = + duplicateTemplateTask._id; + newProjectTemplateChildTask.externalId = + childTaskData.externalId + "-" + UTILS.epochTime(); + + let duplicateChildTemplateTask = + await database.models.projectTemplateTasks.create( + _.omit(newProjectTemplateChildTask, ["_id"]) + ); + + childTaskIdArray.push(duplicateChildTemplateTask._id); + newTaskId.push(duplicateChildTemplateTask._id); + } + } + //update new subtask ids to parent task + if (childTaskIdArray && childTaskIdArray.length > 0) { + let updateTaskData = + await projectTemplateTaskQueries.updateTaskDocument( + { + _id: duplicateTemplateTask._id, + }, + { + $set: { + children: childTaskIdArray, + }, + } ); } - - return resolve( - _.pick( - ratingUpdated, - ["averageRating","noOfRatings","ratings"] - ) - ); - - } catch (error) { - return resolve({ - success : false, - message : error.message, - status : error.status ? error.status : HTTP_STATUS_CODE['internal_server_error'].status - }); + } } - }) - } + } + } - /** - * Project template tasks - * @method - * @name duplicateTemplateTasks - * @param {Array} taskIds - Task ids - * @returns {Object} Duplicated tasks. - */ - - static duplicateTemplateTasks( taskIds=[], duplicateTemplateId, duplicateTemplateExternalId ) { - return new Promise(async (resolve, reject) => { - try { - - let newTaskId = []; - - for ( let pointerToTask = 0; pointerToTask < taskIds.length; pointerToTask++ ) { - - let taskId = taskIds[pointerToTask]; - let taskData = await projectTemplateTaskQueries.taskDocuments( - { - _id : taskId, - parentId : { $exists : false } - }); - - if( taskData && taskData.length > 0 ) { - taskData = taskData[0]; - } - - if ( taskData && Object.keys(taskData).length > 0 ) { - - //duplicate parent task - let newProjectTemplateTask = {...taskData}; - newProjectTemplateTask.projectTemplateId = duplicateTemplateId; - newProjectTemplateTask.projectTemplateExternalId = duplicateTemplateExternalId; - newProjectTemplateTask.externalId = taskData.externalId +"-"+ UTILS.epochTime(); - - let duplicateTemplateTask = - await database.models.projectTemplateTasks.create( - _.omit(newProjectTemplateTask, ["_id"]) - ); - - newTaskId.push(duplicateTemplateTask._id); - - //duplicate child task - if ( duplicateTemplateTask.children && duplicateTemplateTask.children.length > 0 ) { - - let childTaskIdArray = []; - let childTaskIds = duplicateTemplateTask.children; - - if ( childTaskIds && childTaskIds.length > 0 ) { - - for ( let pointerToChild = 0 ; pointerToChild < childTaskIds.length ; pointerToChild++ ) { - - let childtaskId = childTaskIds[pointerToChild]; - let childTaskData = await projectTemplateTaskQueries.taskDocuments( - { - _id : childtaskId - }); - - if ( childTaskData && childTaskData.length > 0 ) { - childTaskData = childTaskData[0]; - } - - if ( childTaskData && Object.keys(childTaskData).length > 0 ) { - - let newProjectTemplateChildTask = {...childTaskData}; - newProjectTemplateChildTask.projectTemplateId = duplicateTemplateId; - newProjectTemplateChildTask.projectTemplateExternalId = duplicateTemplateExternalId; - newProjectTemplateChildTask.parentId = duplicateTemplateTask._id; - newProjectTemplateChildTask.externalId = childTaskData.externalId +"-"+ UTILS.epochTime(); - - let duplicateChildTemplateTask = - await database.models.projectTemplateTasks.create( - _.omit(newProjectTemplateChildTask, ["_id"]) - ); - - childTaskIdArray.push(duplicateChildTemplateTask._id); - newTaskId.push(duplicateChildTemplateTask._id); - } - } - //update new subtask ids to parent task - if(childTaskIdArray && childTaskIdArray.length > 0){ - let updateTaskData = await projectTemplateTaskQueries.updateTaskDocument( - { - _id : duplicateTemplateTask._id - }, - { - $set : { - children : childTaskIdArray - } - }) - } - } - } - } - } + let updateDuplicateTemplate; + //adding duplicate tasj to duplicate template + if (newTaskId && newTaskId.length > 0) { + updateDuplicateTemplate = + await projectTemplateQueries.findOneAndUpdate( + { + _id: duplicateTemplateId, + }, + { + $set: { + tasks: newTaskId, + }, + } + ); + } - let updateDuplicateTemplate; - //adding duplicate tasj to duplicate template - if(newTaskId && newTaskId.length > 0){ - - updateDuplicateTemplate = await projectTemplateQueries.findOneAndUpdate( - { - _id : duplicateTemplateId - }, - { - $set : { - tasks : newTaskId - } - }) - } + return resolve(updateDuplicateTemplate); + } catch (error) { + return reject(error); + } + }); + } - return resolve( - updateDuplicateTemplate - ); - - } catch (error) { - return reject(error); - } - }) - } + /** + * Templates list. + * @method + * @name listByIds + * @param {Array} externalIds - External ids + * @returns {Array} List of templates data. + */ - /** - * Templates list. - * @method - * @name listByIds - * @param {Array} externalIds - External ids - * @returns {Array} List of templates data. - */ - - static listByIds( externalIds ) { - return new Promise(async (resolve, reject) => { - try { - - let templateData = await projectTemplateQueries.templateDocument({ - externalId : { $in : externalIds } - },["title","metaInformation.goal","externalId"]); - - if ( !templateData.length > 0 ) { - throw { - status : HTTP_STATUS_CODE.bad_request.status, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND - } - } + static listByIds(externalIds) { + return new Promise(async (resolve, reject) => { + try { + let templateData = await projectTemplateQueries.templateDocument( + { + externalId: { $in: externalIds }, + }, + ["title", "metaInformation.goal", "externalId"] + ); + + if (!templateData.length > 0) { + throw { + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + }; + } - templateData = templateData.map( template => { - if( template.metaInformation && template.metaInformation.goal ) { - template.goal = template.metaInformation.goal; - delete template.metaInformation; - } + templateData = templateData.map((template) => { + if (template.metaInformation && template.metaInformation.goal) { + template.goal = template.metaInformation.goal; + delete template.metaInformation; + } + + return template; + }); + + return resolve({ + success: false, + data: templateData, + message: CONSTANTS.apiResponses.PROJECT_TEMPLATES_FETCHED, + }); + } catch (error) { + return reject(error); + } + }); + } + + /** + * Template details. + * @method + * @name details + * @param {String} templateId - Project template id. + * @param {String} userId - logged in user id. + * @params {String} link - solution link. + * @returns {Array} Project templates data. + */ + + static details(templateId = "", link = "", userId = "", isAPrivateProgram) { + return new Promise(async (resolve, reject) => { + try { + let solutionsResult = {}; + let findQuery = {}; + //get data when link is given + if (link) { + let queryData = {}; + queryData["link"] = link; + + let solutionDocument = await solutionsQueries.solutionsDocument( + queryData, + [ + "_id", + "name", + "programId", + "programName", + "projectTemplateId", + "link", + ] + ); + + if (!solutionDocument.length > 0) { + throw { + message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } + let solutiondata = solutionDocument; + templateId = solutiondata[0].projectTemplateId; + if (!templateId) { + return resolve({ + success: false, + data: solutiondata, + message: CONSTANTS.apiResponses.TEMPLATE_ID_NOT_FOUND_IN_SOLUTION, + }); + } + solutionsResult = solutiondata; + templateId = templateId.toString(); + } - return template; - }) + if (templateId) { + let validateTemplateId = UTILS.isValidMongoId(templateId); + if (validateTemplateId) { + findQuery["_id"] = templateId; + } else { + findQuery["externalId"] = templateId; + } + } + //getting template data using templateId + + let templateData = await projectTemplateQueries.templateDocument( + findQuery, + "all", + [ + "ratings", + "noOfRatings", + "averageRating", + "parentTemplateId", + "userId", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt", + "__v", + ] + ); + + if (!templateData.length > 0) { + throw { + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + }; + } + if ( + templateData[0].certificateTemplateId && + templateData[0].certificateTemplateId !== "" + ) { + let certificateTemplateDetails = + await certificateTemplateQueries.certificateTemplateDocument( + { + _id: templateData[0].certificateTemplateId, + }, + ["criteria"] + ); + + //certificate template data do not exists. + if (!certificateTemplateDetails.length > 0) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND, + }; + } + templateData[0].criteria = certificateTemplateDetails[0].criteria; + } - return resolve({ - success : false, - data : templateData, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATES_FETCHED - }); - - } catch (error) { - return reject(error); - } - }) - } + if (templateData[0].tasks && templateData[0].tasks.length > 0) { + templateData[0].tasks = await this.tasksAndSubTasks( + templateData[0]._id + ); + } + let result = await _templateInformation(templateData[0]); + if (!result.success) { + return resolve(result); + } - /** - * Template details. - * @method - * @name details - * @param {String} templateId - Project template id. - * @param {String} userId - logged in user id. - * @params {String} link - solution link. - * @returns {Array} Project templates data. - */ - - static details( templateId="", link="", userId="", isAPrivateProgram ) { - return new Promise(async (resolve, reject) => { - try { - let solutionsResult = {}; - let findQuery = {}; - //get data when link is given - if( link ){ - - let queryData = {}; - queryData["link"] =link; - - let solutionDocument = await solutionsQueries.solutionsDocument(queryData, - [ - "_id", - "name", - "programId", - "programName", - "projectTemplateId", - "link" - ] - ); - - if( !solutionDocument.length > 0 ) { - throw { - message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - let solutiondata = solutionDocument; - templateId = solutiondata[0].projectTemplateId; - if( !templateId ){ - return resolve({ - success : false, - data : solutiondata, - message : CONSTANTS.apiResponses.TEMPLATE_ID_NOT_FOUND_IN_SOLUTION - }); - } - solutionsResult = solutiondata; - templateId=templateId.toString(); - } - - if( templateId ){ - let validateTemplateId = UTILS.isValidMongoId(templateId); - if( validateTemplateId ) { - findQuery["_id"] = templateId; - } else { - findQuery["externalId"] = templateId; - } + if (!templateData[0].isReusable && userId !== "") { + templateData[0].projectId = ""; + + const projectIdQuery = { + userId: userId, + projectTemplateId: templateData[0]._id, + }; + + if (isAPrivateProgram !== "") { + projectIdQuery.isAPrivateProgram = isAPrivateProgram; + } + let project = await projectQueries.projectDocument(projectIdQuery, [ + "_id", + "hasAcceptedTAndC", + ]); + + if (project && project.length > 0) { + templateData[0].projectId = project[0]._id; + templateData[0].hasAcceptedTAndC = project[0].hasAcceptedTAndC; + } + } + if (!result.data.programInformation) { + result.data.programInformation = { + programId: solutionsResult.programId, + programName: solutionsResult.programName, + }; + } + result.data.solutionInformation = { + _id: solutionsResult._id, + name: solutionsResult.name, + link: solutionsResult.link, + }; + return resolve({ + success: false, + data: result.data, + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED, + }); + } catch (error) { + return reject(error); + } + }); + } - } - //getting template data using templateId - - let templateData = await projectTemplateQueries.templateDocument(findQuery,"all", - [ - "ratings", - "noOfRatings", - "averageRating", - "parentTemplateId", - "userId", - "createdBy", - "updatedBy", - "createdAt", - "updatedAt", - "__v" - ] - ); - - if ( !templateData.length > 0 ) { - throw { - status : HTTP_STATUS_CODE.bad_request.status, - message :CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND - } - } - if ( templateData[0].certificateTemplateId && templateData[0].certificateTemplateId !== "" ){ - let certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : templateData[0].certificateTemplateId - },["criteria"]); - - //certificate template data do not exists. - if ( !certificateTemplateDetails.length > 0 ) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND - }; - } - templateData[0].criteria = certificateTemplateDetails[0].criteria - } + /** + * Tasks and sub tasks. + * @method + * @name tasksAndSubTasks + * @param {Array} templateId - Template id. + * @returns {Array} Tasks and sub task. + */ - if (templateData[0].tasks && templateData[0].tasks.length > 0) { - templateData[0].tasks = - await this.tasksAndSubTasks(templateData[0]._id); - } - let result = await _templateInformation(templateData[0]) - if( !result.success ) { - return resolve(result); - } - - if( !templateData[0].isReusable && userId !== "") { - - templateData[0].projectId = ""; - - const projectIdQuery = { - userId : userId, - projectTemplateId : templateData[0]._id, - } - - if( isAPrivateProgram !== ""){ - projectIdQuery.isAPrivateProgram = isAPrivateProgram - } - let project = await projectQueries.projectDocument( - projectIdQuery - ,["_id"]); - - if(project && project.length > 0){ - templateData[0].projectId = project[0]._id; - } - } - if( !result.data.programInformation ){ - result.data.programInformation = { - programId : solutionsResult.programId, - programName : solutionsResult.programName - } - } - result.data.solutionInformation = { - _id : solutionsResult._id, - name : solutionsResult.name, - link : solutionsResult.link - } - return resolve({ - success : false, - data : result.data, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_DETAILS_FETCHED - }); - - } catch (error) { - return reject(error); + static tasksAndSubTasks(templateId) { + return new Promise(async (resolve, reject) => { + try { + const templateDocument = await projectTemplateQueries.templateDocument( + { + _id: templateId, + status: CONSTANTS.common.PUBLISHED, + }, + ["tasks", "taskSequence"] + ); + + let tasks = []; + + if ( + templateDocument[0].taskSequence && + templateDocument[0].taskSequence.length > 0 + ) { + let projectionKey = CONSTANTS.common.TASK_SEQUENCE; + let findQuery = { + externalId: { + $in: templateDocument[0].taskSequence, + }, + }; + + tasks = await _taskAndSubTaskinSequence(findQuery, projectionKey); + } else { + if ( + templateDocument[0].tasks && + templateDocument[0].tasks.length > 0 + ) { + let projectionKey = CONSTANTS.common.CHILDREN; + if (templateDocument[0].tasks) { + let findQuery = { + _id: { + $in: templateDocument[0].tasks, + }, + parentId: { $exists: false }, + }; + + tasks = await _taskAndSubTaskinSequence(findQuery, projectionKey); } - }) - } - - /** - * Tasks and sub tasks. - * @method - * @name tasksAndSubTasks - * @param {Array} templateId - Template id. - * @returns {Array} Tasks and sub task. - */ - - static tasksAndSubTasks(templateId) { - return new Promise(async (resolve, reject) => { - try { - - const templateDocument = - await projectTemplateQueries.templateDocument({ - _id : templateId, - status : CONSTANTS.common.PUBLISHED - },["tasks", "taskSequence"]); - - let tasks = []; - - if ( templateDocument[0].taskSequence && templateDocument[0].taskSequence.length > 0 ) { - - let projectionKey = CONSTANTS.common.TASK_SEQUENCE; - let findQuery = { - externalId : { - $in : templateDocument[0].taskSequence - } - } - - tasks = await _taskAndSubTaskinSequence(findQuery, projectionKey); - } else { - if ( templateDocument[0].tasks && templateDocument[0].tasks.length > 0 ){ - let projectionKey = CONSTANTS.common.CHILDREN; - if( templateDocument[0].tasks ) { - let findQuery = { - _id : { - $in : templateDocument[0].tasks - }, - parentId : { $exists : false } - } - - tasks = await _taskAndSubTaskinSequence(findQuery, projectionKey); - } - } - - } - - return resolve(tasks); - - } catch (error) { - return reject(error); - } - }); - } - - /** - * Template update. - * @method - * @name update - * @param {String} templateId - Project template id. - * @param {Object} templateData - template updation data - * @param {String} userId - logged in user id. - * @returns {Array} Project templates data. - */ - - static update( templateId, templateData, userId ) { - return new Promise(async (resolve, reject) => { - try { + } + } - let findQuery = {}; + return resolve(tasks); + } catch (error) { + return reject(error); + } + }); + } + + /** + * Template update. + * @method + * @name update + * @param {String} templateId - Project template id. + * @param {Object} templateData - template updation data + * @param {String} userId - logged in user id. + * @returns {Array} Project templates data. + */ + + static update(templateId, templateData, userId) { + return new Promise(async (resolve, reject) => { + try { + let findQuery = {}; - let validateTemplateId = UTILS.isValidMongoId(templateId); + let validateTemplateId = UTILS.isValidMongoId(templateId); - if( validateTemplateId ) { - findQuery["_id"] = templateId; - } else { - findQuery["externalId"] = templateId; - } - - let templateDocument = await projectTemplateQueries.templateDocument(findQuery, ["_id"]); + if (validateTemplateId) { + findQuery["_id"] = templateId; + } else { + findQuery["externalId"] = templateId; + } - if ( !templateDocument.length > 0 ) { - throw { - status : HTTP_STATUS_CODE.bad_request.status, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND - } - } + let templateDocument = await projectTemplateQueries.templateDocument( + findQuery, + ["_id"] + ); - let updateObject = { - "$set" : {} - }; + if (!templateDocument.length > 0) { + throw { + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + }; + } - let templateUpdateData = templateData; + let updateObject = { + $set: {}, + }; - Object.keys(templateUpdateData).forEach(updationData=>{ - updateObject["$set"][updationData] = templateUpdateData[updationData]; - }); + let templateUpdateData = templateData; - updateObject["$set"]["updatedBy"] = userId; + Object.keys(templateUpdateData).forEach((updationData) => { + updateObject["$set"][updationData] = templateUpdateData[updationData]; + }); - let templateUpdatedData = await projectTemplateQueries.findOneAndUpdate({ - _id : templateDocument[0]._id - }, updateObject, { new : true }); + updateObject["$set"]["updatedBy"] = userId; - if( !templateUpdatedData._id ) { - throw { - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED - } - } + let templateUpdatedData = await projectTemplateQueries.findOneAndUpdate( + { + _id: templateDocument[0]._id, + }, + updateObject, + { new: true } + ); - return resolve({ - success : true, - data : templateUpdatedData, - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_UPDATED - }); - - } catch (error) { - return reject(error); - } - }) - } + if (!templateUpdatedData._id) { + throw { + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_UPDATED, + }; + } + return resolve({ + success: true, + data: templateUpdatedData, + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_UPDATED, + }); + } catch (error) { + return reject(error); + } + }); + } }; /** @@ -1244,137 +1262,140 @@ module.exports = class ProjectTemplatesHelper { * @name _calculateRating * @param {Object} ratings - Ratings data. * @returns {Object} rating object. -*/ + */ function _calculateRating(ratings) { - let sum = 0; - let noOfRatings = 0; - - Object.keys(ratings).forEach(rating => { - sum += rating * ratings[rating]; - noOfRatings += ratings[rating]; - }); - - return { - averageRating : (sum/noOfRatings).toFixed(2), - noOfRatings : noOfRatings - } + let sum = 0; + let noOfRatings = 0; + + Object.keys(ratings).forEach((rating) => { + sum += rating * ratings[rating]; + noOfRatings += ratings[rating]; + }); + + return { + averageRating: (sum / noOfRatings).toFixed(2), + noOfRatings: noOfRatings, + }; } /** * Project information. * @method - * @name _templateInformation + * @name _templateInformation * @param {Object} project - Project data. * @returns {Object} Project information. -*/ + */ function _templateInformation(project) { - - return new Promise(async (resolve, reject) => { - try { - - if( project.programId ) { - - let programs = - await surveyService.listProgramsBasedOnIds([project.programId]); - - if( !programs.success ) { - throw { - message : CONSTANTS.apiResponses.PROGRAM_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - project.programInformation = { - programId : project.programId, - programName : programs.data[0].name - } - - delete project.programId; - delete project.programExternalId; - } - - if (project.metaInformation) { - Object.keys(project.metaInformation).forEach(projectMetaKey => { - project[projectMetaKey] = project.metaInformation[projectMetaKey]; - }); - } - delete project.metaInformation; - delete project.__v; - - project.status = - project.status ? project.status : CONSTANTS.common.NOT_STARTED_STATUS; - - return resolve({ - success: true, - data: project - }); - - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }) + return new Promise(async (resolve, reject) => { + try { + if (project.programId) { + let programs = await surveyService.listProgramsBasedOnIds([ + project.programId, + ]); + + if (!programs.success) { + throw { + message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; } - }) + + project.programInformation = { + programId: project.programId, + programName: programs.data[0].name, + }; + + delete project.programId; + delete project.programExternalId; + } + + if (project.metaInformation) { + Object.keys(project.metaInformation).forEach((projectMetaKey) => { + project[projectMetaKey] = project.metaInformation[projectMetaKey]; + }); + } + delete project.metaInformation; + delete project.__v; + + project.status = project.status + ? project.status + : CONSTANTS.common.NOT_STARTED_STATUS; + + return resolve({ + success: true, + data: project, + }); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); } /** * Task and SubTask In Order. * @method - * @name _taskAndSubTaskinSequence + * @name _taskAndSubTaskinSequence * @param {Object} query - template Query. * @param {String} projectionValue - children or taskSequence. * @returns {Object} Task and SubTask information. -*/ + */ function _taskAndSubTaskinSequence(query, projectionValue) { - - return new Promise(async (resolve, reject) => { - try { - - let tasks = []; - tasks = await projectTemplateTaskQueries.taskDocuments(query,"all", ["projectTemplateId","__v","projectTemplateExternalId"]); - - for( let task = 0 ; task < tasks.length ; task++ ) { - if ( tasks[task][projectionValue] && tasks[task][projectionValue].length > 0 ) { - let subTaskQuery; - if ( projectionValue == CONSTANTS.common.CHILDREN ) { - subTaskQuery = { - "_id" : { - $in : tasks[task][projectionValue] - } - } - - } else { - subTaskQuery = { - "externalId" : { - $in : tasks[task][projectionValue] - } - } - } - - let subTasks = await projectTemplateTaskQueries.taskDocuments(subTaskQuery, "all", ["projectTemplateId","__v","projectTemplateExternalId"]); - tasks[task].children = subTasks; - } - } - - return resolve(tasks); - - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }) + return new Promise(async (resolve, reject) => { + try { + let tasks = []; + tasks = await projectTemplateTaskQueries.taskDocuments(query, "all", [ + "projectTemplateId", + "__v", + "projectTemplateExternalId", + ]); + + for (let task = 0; task < tasks.length; task++) { + if ( + tasks[task][projectionValue] && + tasks[task][projectionValue].length > 0 + ) { + let subTaskQuery; + if (projectionValue == CONSTANTS.common.CHILDREN) { + subTaskQuery = { + _id: { + $in: tasks[task][projectionValue], + }, + }; + } else { + subTaskQuery = { + externalId: { + $in: tasks[task][projectionValue], + }, + }; + } + + let subTasks = await projectTemplateTaskQueries.taskDocuments( + subTaskQuery, + "all", + ["projectTemplateId", "__v", "projectTemplateExternalId"] + ); + tasks[task].children = subTasks; } - }) + } + + return resolve(tasks); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); } - - From d4a668b4677b7b0b11457d8fb958fc0cd58f75ec Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Sun, 2 Jul 2023 09:06:58 +0530 Subject: [PATCH 304/373] ED-2448 --- module/userProjects/helper.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 72bd9f22..4086bfcf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1263,6 +1263,9 @@ module.exports = class UserProjectsHelper { if( bodyData.hasAcceptedTAndC ) { projectCreation.data.hasAcceptedTAndC = bodyData.hasAcceptedTAndC; } + if( bodyData.link ) { + projectCreation.data.link = bodyData.link; + } if( bodyData.referenceFrom ) { projectCreation.data.referenceFrom = bodyData.referenceFrom; From de1cc8fb13c8ae0e8a0d510afa4af3ee8a76bcb7 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 3 Jul 2023 14:05:51 +0530 Subject: [PATCH 305/373] ED-2448 --- module/userProjects/helper.js | 118 ++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 4 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4086bfcf..1776ab41 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -455,7 +455,7 @@ module.exports = class UserProjectsHelper { userToken, isATargetedSolution ); - + if (!solutionAndProgramCreation.success) { throw { status: HTTP_STATUS_CODE['bad_request'].status, @@ -490,6 +490,102 @@ module.exports = class UserProjectsHelper { result["link"] = solutionAndProgramCreation.data.parentSolutionInformation.link ? solutionAndProgramCreation.data.parentSolutionInformation.link : ""; } + return resolve({ + success: true, + data: result + }); + + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); + } + }); + } + + /** + * Program and solution information + * @method + * @name getProgramAndSolutionDetails + * @param {String} solutionId - solutionId. + * @returns {Object} return program and solution data. + */ + + static getProgramAndSolutionDetails( + solutionId + ) { + return new Promise(async (resolve, reject) => { + try { + + let result = {}; + // Fetch private solution details from DB + let solutionDetails = await solutionsHelper.solutionDocuments({ + _id: solutionId, + isAPrivateProgram: true + }, + [ + "_id", + "name", + "externalId", + "description", + "programId", + "programName", + "programDescription", + "programExternalId", + "isAPrivateProgram", + "projectTemplateId", + "entityType", + "certificateTemplateId", + "parentSolutionId" + ]); + + if (!solutionDetails.length > 0 || !solutionDetails[0].parentSolutionId ) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.SOLUTION_PROGRAMS_NOT_CREATED + }; + } + + solutionDetails = solutionDetails[0]; + // Adding solution information + result.solutionInformation = _.pick( + solutionDetails, + ["name", "externalId", "description", "_id", "entityType", "certificateTemplateId"] + ); + + result.solutionInformation._id = + ObjectId(result.solutionInformation._id); + + result["solutionId"] = ObjectId(result.solutionInformation._id); + result["solutionExternalId"] = result.solutionInformation.externalId; + + // Adding program informations + result.programInformation = { + _id: solutionDetails.programId, + description: solutionDetails.programDescription, + externalId: solutionDetails.programExternalId, + isAPrivateProgram: solutionDetails.isAPrivateProgram, + name: solutionDetails.programName + }; + + + result["programId"] = ObjectId(result.programInformation._id); + result["programExternalId"] = result.programInformation.externalId; + result["isAPrivateProgram"] = result.programInformation.isAPrivateProgram; + + result.programInformation._id = + ObjectId(result.programInformation._id); + + let solutionData = await solutionsHelper.solutionDocuments({ + _id: solutionDetails.parentSolutionId, + }, + ["link"]); + result["link"] = (solutionData.length > 0 && solutionData[0].link ) ? solutionData[0].link : ""; return resolve({ success: true, @@ -2288,8 +2384,21 @@ module.exports = class UserProjectsHelper { } if( requestedData.solutionId && requestedData.solutionId !== "" && isATargetedSolution === false ){ - - let programAndSolutionInformation = + let programAndSolutionInformation = {}; + // Check if solutionId passed is private or not, if private and data is present, create program and solution information. + let solutionDetails = await solutionsHelper.solutionDocuments({ + _id: requestedData.solutionId, + isAPrivateProgram: true + }, + [ + "_id" + ]); + // private solution exists + if ( solutionDetails.length > 0 ) { + // This function will return programAndSolutionInformation + programAndSolutionInformation = await this.getProgramAndSolutionDetails(requestedData.solutionId); + } else { + programAndSolutionInformation = await this.createProgramAndSolution( requestedData.programId, requestedData.programName, @@ -2298,7 +2407,8 @@ module.exports = class UserProjectsHelper { requestedData.solutionId, isATargetedSolution ); - + } + if (!programAndSolutionInformation.success) { return resolve(programAndSolutionInformation); } From ec3a21904264f319759bdaad6acd7bc2872ff93e Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 3 Jul 2023 14:10:18 +0530 Subject: [PATCH 306/373] ED-2448 changes --- module/userProjects/helper.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1776ab41..19451e15 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -580,12 +580,13 @@ module.exports = class UserProjectsHelper { result.programInformation._id = ObjectId(result.programInformation._id); - + // Get link from parent solution let solutionData = await solutionsHelper.solutionDocuments({ _id: solutionDetails.parentSolutionId, }, ["link"]); - result["link"] = (solutionData.length > 0 && solutionData[0].link ) ? solutionData[0].link : ""; + + result["link"] = ( solutionData.length > 0 && solutionData[0].link ) ? solutionData[0].link : ""; return resolve({ success: true, From a2004348d1b320c54468af650f74db4b853e26cb Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 4 Jul 2023 09:00:39 +0530 Subject: [PATCH 307/373] ED-2448 review changes --- module/userProjects/helper.js | 52 ++++++++++++----------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 19451e15..98c6cfcd 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -512,47 +512,17 @@ module.exports = class UserProjectsHelper { * Program and solution information * @method * @name getProgramAndSolutionDetails - * @param {String} solutionId - solutionId. + * @param {Object} solutionDetails - solution details. * @returns {Object} return program and solution data. */ static getProgramAndSolutionDetails( - solutionId + solutionDetails ) { return new Promise(async (resolve, reject) => { try { let result = {}; - // Fetch private solution details from DB - let solutionDetails = await solutionsHelper.solutionDocuments({ - _id: solutionId, - isAPrivateProgram: true - }, - [ - "_id", - "name", - "externalId", - "description", - "programId", - "programName", - "programDescription", - "programExternalId", - "isAPrivateProgram", - "projectTemplateId", - "entityType", - "certificateTemplateId", - "parentSolutionId" - ]); - - if (!solutionDetails.length > 0 || !solutionDetails[0].parentSolutionId ) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.SOLUTION_PROGRAMS_NOT_CREATED - }; - } - - solutionDetails = solutionDetails[0]; - // Adding solution information result.solutionInformation = _.pick( solutionDetails, ["name", "externalId", "description", "_id", "entityType", "certificateTemplateId"] @@ -2392,12 +2362,24 @@ module.exports = class UserProjectsHelper { isAPrivateProgram: true }, [ - "_id" + "_id", + "name", + "externalId", + "description", + "programId", + "programName", + "programDescription", + "programExternalId", + "isAPrivateProgram", + "projectTemplateId", + "entityType", + "certificateTemplateId", + "parentSolutionId" ]); // private solution exists - if ( solutionDetails.length > 0 ) { + if ( solutionDetails.length > 0 && solutionDetails[0].parentSolutionId ) { // This function will return programAndSolutionInformation - programAndSolutionInformation = await this.getProgramAndSolutionDetails(requestedData.solutionId); + programAndSolutionInformation = await this.getProgramAndSolutionDetails(solutionDetails[0]); } else { programAndSolutionInformation = await this.createProgramAndSolution( From be615d1908724299503ffee8af6560df0b010813 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 4 Jul 2023 09:37:17 +0530 Subject: [PATCH 308/373] Review changes --- module/userProjects/helper.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 98c6cfcd..5bc8aa76 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2379,6 +2379,12 @@ module.exports = class UserProjectsHelper { // private solution exists if ( solutionDetails.length > 0 && solutionDetails[0].parentSolutionId ) { // This function will return programAndSolutionInformation + /** + * function privateProgramAndSolutionDetails + * Request: + * @param {solutionDetails} solution data + * @response Program and solution details + */ programAndSolutionInformation = await this.getProgramAndSolutionDetails(solutionDetails[0]); } else { programAndSolutionInformation = From 3e232422885bf7fb0aee328e6245aa3846c1875b Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Tue, 4 Jul 2023 10:00:40 +0530 Subject: [PATCH 309/373] function response added --- module/userProjects/helper.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 5bc8aa76..74470a0b 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -514,6 +514,32 @@ module.exports = class UserProjectsHelper { * @name getProgramAndSolutionDetails * @param {Object} solutionDetails - solution details. * @returns {Object} return program and solution data. + * example : + * response : { + "success":true, + "data":{ + "solutionInformation":{ + "name":"Keep Our Schools Alive (Petition) - With Certificate 2", + "externalId":"IDEAIMP-4-1687489894154-PROJECT-SOLUTION-1688365299788", + "description":"Leveraging the huge number of private schools to show the significance of the financial problem by creating a petition and presenting to the authorities.", + "_id":64a268f34b9d0c124fd8ed80, + "certificateTemplateId":64950d67955f600008e2aff3 + }, + "solutionId":64a268f34b9d0c124fd8ed80, + "solutionExternalId":"IDEAIMP-4-1687489894154-PROJECT-SOLUTION-1688365299788", + "programInformation":{ + "_id":64a268f34b9d0c124fd8ed7d, + "description":"Certificate Test Program 6.0", + "externalId":"Pgm_Certificate_Test_Program_6.0_QA-1688365299788", + "isAPrivateProgram":true, + "name":"Certificate Test Program 6.0" + }, + "programId":64a268f34b9d0c124fd8ed7d, + "programExternalId":"Pgm_Certificate_Test_Program_6.0_QA-1688365299788", + "isAPrivateProgram":true, + "link":"750f4f6ebb390ad5f7038a8fbc8e1c3f" + } + } */ static getProgramAndSolutionDetails( From 2459bfff76689fbbbf2435ff05952431cbe4bb65 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 10 Jul 2023 11:03:28 +0530 Subject: [PATCH 310/373] Fix ED-2556 --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 74470a0b..a76dc927 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -2245,7 +2245,8 @@ module.exports = class UserProjectsHelper { "programInformation", "title", "description", - "projectTemplateId" + "projectTemplateId", + "certificate.templateId" ] ); From 80de5566d3dcc00533a9ff1429dc8bf1362d4dd1 Mon Sep 17 00:00:00 2001 From: VISHNUDAS-tunerlabse Date: Mon, 10 Jul 2023 17:36:02 +0530 Subject: [PATCH 311/373] remove link from userRoleInformation --- module/userProjects/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index a76dc927..3abbe4ea 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1161,7 +1161,7 @@ module.exports = class UserProjectsHelper { solutionExternalId = templateDocuments[0].solutionExternalId; } - let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC"]); + let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); if (projectId === "") { // This will check wether the user user is targeted to solution or not based on his userRoleInformation From 768d598d82b63683e0ef7d1fabbd861056f9ea95 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 12 Jul 2023 14:06:28 +0530 Subject: [PATCH 312/373] Added Release Tag --- release-notes/6.0.0.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/release-notes/6.0.0.md b/release-notes/6.0.0.md index bd1ab572..6395cd1b 100644 --- a/release-notes/6.0.0.md +++ b/release-notes/6.0.0.md @@ -2,11 +2,9 @@ This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Projects service code to 6.0.0. Please consider the following list of tasks to be completed. - ### Deploy ml-projects-services -To retrieve the latest release tag for version 6.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-6.0.0_RC3 - +To retrieve the latest release tag for version 6.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-6.0.0_RC7 To proceed with the deployment process, follow the steps below: From 438e7a78d69022dfa22fa12faa36a6ec01bf512b Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 19 Jul 2023 10:14:12 +0530 Subject: [PATCH 313/373] Added setup guide and db schema along with example --- DBSchema/certificateTemplates.json | 72 + DBSchema/programUsers.json | 16 + DBSchema/programs.json | 90 ++ DBSchema/projectTemplateTasks.json | 46 + DBSchema/projectTemplates.json | 65 + DBSchema/projects.json | 2060 ++++++++++++++++++++++++++++ DBSchema/solutions.json | 469 +++++++ README.md | 134 +- 8 files changed, 2951 insertions(+), 1 deletion(-) create mode 100644 DBSchema/certificateTemplates.json create mode 100644 DBSchema/programUsers.json create mode 100644 DBSchema/programs.json create mode 100644 DBSchema/projectTemplateTasks.json create mode 100644 DBSchema/projectTemplates.json create mode 100644 DBSchema/projects.json create mode 100644 DBSchema/solutions.json diff --git a/DBSchema/certificateTemplates.json b/DBSchema/certificateTemplates.json new file mode 100644 index 00000000..9d5c9bfd --- /dev/null +++ b/DBSchema/certificateTemplates.json @@ -0,0 +1,72 @@ +{ + "_id" : "637cb340261b7c0008253fa6", + "status" : "active", + "deleted" : false, + "criteria" : { + "validationText" : "Complete validation message", + "expression" : "C1&&C2&&C3", + "conditions" : { + "C1" : { + "validationText" : "Project Should be submitted within program Enddate", + "expression" : "C1&&C2", + "conditions" : { + "C1" : { + "scope" : "project", + "key" : "status", + "operator" : "==", + "value" : "submitted" + }, + "C2" : { + "scope" : "project", + "key" : "completedDate", + "operator" : "<", + "value" : "15-08-2022" + } + } + }, + "C2" : { + "validationText" : "Evidence project level validation", + "expression" : "C1", + "conditions" : { + "C1" : { + "scope" : "project", + "key" : "attachments", + "function" : "count", + "filter" : { + "key" : "type", + "value" : "all" + }, + "operator" : ">", + "value" : 1 + } + } + }, + "C3" : { + "validationText" : "Evidence task level validation", + "expression" : "C1", + "conditions" : { + "C1" : { + "scope" : "task", + "key" : "attachments", + "function" : "count", + "filter" : { + "key" : "type", + "value" : "all" + }, + "operator" : ">", + "value" : 1 + } + } + } + } + }, + "issuer" : { + "name" : "Gujarat" + }, + "solutionId" : "5ff9dc1b9259097d48017bbe", + "programId" : "605083ba09b7bd61555580fb", + "updatedAt" : "2022-11-22T11:37:37.495+0000", + "createdAt" : "2022-11-22T11:32:16.639+0000", + "__v" : 0, + "templateUrl" : "certificateTemplates/637cb340261b7c0008253fa6/ba9aa220-ff1b-4717-b6ea-ace55f04fc16_22-10-2022-1669117057492.svg" +} \ No newline at end of file diff --git a/DBSchema/programUsers.json b/DBSchema/programUsers.json new file mode 100644 index 00000000..4f830432 --- /dev/null +++ b/DBSchema/programUsers.json @@ -0,0 +1,16 @@ +{ + "_id": "645358eb6144f31d8e8fcef4", + "programId": "5f75b90454670074deacf087", + "userId": "f5591238-63c8-4716-a1c9-27c18a32a4d4", + "__v": 0, + "createdAt": "2023-05-04T07:04:11.874Z", + "resourcesStarted": false, + "updatedAt": "2023-05-04T07:04:11.874Z", + "userProfile": null, + "userRoleInformation": { + "role": "HM", + "state": "db331a8c-b9e2-45f8-b3c0-7ec1e826b6df", + "district": "1dcbc362-ec4c-4559-9081-e0c2864c2931", + "school": "c5726207-4f9f-4f45-91f1-3e9e8e84d824" + } +} \ No newline at end of file diff --git a/DBSchema/programs.json b/DBSchema/programs.json new file mode 100644 index 00000000..dc262202 --- /dev/null +++ b/DBSchema/programs.json @@ -0,0 +1,90 @@ +[ + { + "_id":"5f34e44681871d939950bca6", + "resourceType":[ + "Program" + ], + "language":[ + "English" + ], + "keywords":[ + "keywords 1", + "keywords 2" + ], + "concepts":[ + + ], + "createdFor":[ + "01235953109336064029450" + ], + "components":[ + "5f34e44681871d939950bca7" + ], + "isAPrivateProgram":false, + "rootOrganisations":[ + "01235953109336064029450" + ], + "deleted":false, + "externalId":"TN-Program-1597301830708", + "name":"TN-Program", + "description":"TN01-Mantra4Change-APSWREIS School Leader Feedback", + "owner":"140558b9-7df4-4993-be3c-31eb8b9ca368", + "createdBy":"140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy":"140558b9-7df4-4993-be3c-31eb8b9ca368", + "status":"active", + "imageCompression":{ + "quality":10 + }, + "updatedAt":"2020-08-13T06:57:10.710+0000", + "createdAt":"2020-08-13T06:57:10.710+0000", + "__v":0 + }, + { + "_id":"5f35044f19377eecddb06921", + "resourceType":[ + "Program" + ], + "language":[ + "English" + ], + "keywords":[ + "keywords 1", + "keywords 2" + ], + "concepts":[ + + ], + "createdFor":[ + "0123221617357783046602" + ], + "components":[ + "5f35044f19377eecddb06922", + "5f3bc2d86ba5e3ecd7a42231", + "5f3bc2f16ba5e3ecd7a42233", + "5f3bc30a6ba5e3ecd7a42235", + "5f3bc31d6ba5e3ecd7a42237", + "5f3bc3306ba5e3ecd7a42239", + "5f3bc3456ba5e3ecd7a4223b", + "5f3bc38219377eecddb0695a", + "5f9f097cd1b9b71dbfed5f46" + ], + "isAPrivateProgram":true, + "rootOrganisations":[ + "0123221617357783046602" + ], + "deleted":false, + "externalId":"Test Program-1597310031178", + "name":"Test Program", + "description":"Test - Mantra4Change-APSWREIS School Leader Feedback", + "owner":"86d2d978-5b20-4453-8a76-82b5a4c728c9", + "createdBy":"86d2d978-5b20-4453-8a76-82b5a4c728c9", + "updatedBy":"86d2d978-5b20-4453-8a76-82b5a4c728c9", + "status":"active", + "imageCompression":{ + "quality":10 + }, + "updatedAt":"2020-08-13T09:13:51.180+0000", + "createdAt":"2020-08-13T09:13:51.180+0000", + "__v":0 + } + ] \ No newline at end of file diff --git a/DBSchema/projectTemplateTasks.json b/DBSchema/projectTemplateTasks.json new file mode 100644 index 00000000..65ab966f --- /dev/null +++ b/DBSchema/projectTemplateTasks.json @@ -0,0 +1,46 @@ +[ + { + "_id": "5fd244911233354b094f16e4", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6fa0", + "name": "Start planning the fest or cultural programme.", + "externalId": "IMP-3147bk-TASK5", + "description": "", + "updatedAt": "2020-12-10T15:53:53.016+0000", + "createdAt": "2020-12-10T15:53:53.016+0000", + "__v": 0, + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147bk" + }, + { + "_id": "5fd244911233354b094f16e5", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6fa0", + "name": "Find trainers who can volunteer their time to help students practise.", + "externalId": "IMP-3147bk-TASK6", + "description": "", + "updatedAt": "2020-12-10T15:53:53.019+0000", + "createdAt": "2020-12-10T15:53:53.019+0000", + "__v": 0, + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147bk" + } +] diff --git a/DBSchema/projectTemplates.json b/DBSchema/projectTemplates.json new file mode 100644 index 00000000..009de5eb --- /dev/null +++ b/DBSchema/projectTemplates.json @@ -0,0 +1,65 @@ +[ + { + "_id": "5fcf9954546a92494f2e587c", + "title": "test", + "externalId": "5bd5c4a6-0ccc-41fe-9633-d61ed5378a77", + "categories": [], + "duration": { + "value": "1W", + "label": "1 Week" + }, + "difficultyLevel": { + "value": "B", + "label": "Basic" + }, + "description": "test", + "concepts": [""], + "keywords": [""], + "status": "published", + "isDeleted": false, + "recommendedFor": [], + "tasks": [], + "createdAt": "2020-12-08T15:18:44+00:00", + "updatedAt": "2022-11-25T05:48:13.665+0000", + "createdBy": "SYSTEM", + "updatedBy": null, + "learningResources": [], + "isReusable": true, + "entityType": [], + "taskSequence": [], + "metaInformation": { + "supportingDocuments": [""], + "primaryAudience": [""] + } + }, + { + "_id": "5fcf9954546a92494f2e587f", + "title": "Vidyagama facilitation project", + "externalId": "da9f31a1-dc9d-4665-9af4-d023258dc558", + "categories": [], + "duration": { + "value": "1W", + "label": "1 Week" + }, + "difficultyLevel": { + "value": "B", + "label": "Basic" + }, + "description": "Support HMs and teachers by identifying common good practices and challenges with respect to Vidyagama", + "concepts": [], + "keywords": [""], + "status": "published", + "isDeleted": false, + "recommendedFor": [], + "tasks": ["5fcf9954546a92494f2e587d", "5fcf9954546a92494f2e587e"], + "createdAt": "2020-12-08T15:18:44+00:00", + "updatedAt": "2020-12-08T15:18:44+00:00", + "createdBy": "SYSTEM", + "updatedBy": "SYSTEM", + "learningResources": [], + "isReusable": true, + "entityType": [], + "taskSequence": ["5fcf9954546a92494f2e587d", "5fcf9954546a92494f2e587e"], + "metaInformation": {} + } +] diff --git a/DBSchema/projects.json b/DBSchema/projects.json new file mode 100644 index 00000000..5049d2a9 --- /dev/null +++ b/DBSchema/projects.json @@ -0,0 +1,2060 @@ +[ + { + "_id": "6017ce2ed0993d433a596de0", + "userId": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "userRole": "CHM", + "createdFor": ["0126796199493140480", "01275629649735680040708"], + "status": "started", + "isDeleted": false, + "categories": [ + { + "_id": "5fcfa9a2457d6055e33843f2", + "externalId": "community", + "name": "Community" + } + ], + "createdBy": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "tasks": [ + { + "_id": "e4b85120-b2c6-41ce-9a04-e3c05ba2a9d7", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "f742154a-793c-45d6-b61e-c49a65b1047a", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "e4b85120-b2c6-41ce-9a04-e3c05ba2a9d7", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Look for videos and case studies which capture the parent mela or parent meeting conducted in different schools. Focus on the ideas being used and themes being selected.", + "externalId": "IMP-3147aa-TASK7", + "description": "", + "updatedAt": "2021-02-01T09:47:26.173+0000", + "createdAt": "2020-12-10T15:53:31.476+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d5", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.173+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Look for samples of parent mela/ excitement building parent meeting from different schools", + "externalId": "IMP-3147aa-TASK1-1611320352803", + "description": "", + "updatedAt": "2021-02-01T09:47:26.173+0000", + "createdAt": "2020-12-10T15:53:31.460+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.173+0000" + }, + { + "_id": "9bf13931-a814-4f5f-bae9-f5eba9085913", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "d833bae3-0788-4d66-82aa-4543b0c5fa57", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "9bf13931-a814-4f5f-bae9-f5eba9085913", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "-Meeting with teachers to discuss the importance and role of parent mela in improving community engagement in the school.", + "externalId": "IMP-3147aa-TASK8", + "description": "", + "updatedAt": "2021-02-01T09:47:26.173+0000", + "createdAt": "2020-12-10T15:53:31.481+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d6", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.173+0000" + }, + { + "_id": "9ff85ddf-3c04-41c8-b5bb-8be77955b760", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "9bf13931-a814-4f5f-bae9-f5eba9085913", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "-Discuss stories from other schools.", + "externalId": "IMP-3147aa-TASK13", + "description": "", + "updatedAt": "2021-02-01T09:47:26.173+0000", + "createdAt": "2020-12-10T15:53:31.509+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d6", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.173+0000" + }, + { + "_id": "f6d32bed-f497-4378-95c3-db89901e2b24", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "9bf13931-a814-4f5f-bae9-f5eba9085913", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "- Form a committee among teachers to plan and facilitate the mela along with the school leader.", + "externalId": "IMP-3147aa-TASK14", + "description": "", + "updatedAt": "2021-02-01T09:47:26.173+0000", + "createdAt": "2020-12-10T15:53:31.521+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d6", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.173+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Form a parent mela committee among the teachers", + "externalId": "IMP-3147aa-TASK2-1611320352805", + "description": "", + "updatedAt": "2021-02-01T09:47:26.173+0000", + "createdAt": "2020-12-10T15:53:31.463+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.173+0000" + }, + { + "_id": "954511f2-d7ab-4e6d-acde-a9fa9c76768e", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "95a157d9-47bd-4095-ae1e-cc367deed3c6", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "954511f2-d7ab-4e6d-acde-a9fa9c76768e", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Finalize the themes and activities for the mela. This could be taken borrowed from other schools or decided by the teachers through brainstorming. \nFinalize the dates for the same", + "externalId": "IMP-3147aa-TASK9", + "description": "", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-10T15:53:31.487+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d7", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Planning for the mela", + "externalId": "IMP-3147aa-TASK3-1611320352808", + "description": "", + "updatedAt": "2021-02-01T09:47:26.173+0000", + "createdAt": "2020-12-10T15:53:31.465+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + }, + { + "_id": "2160c6bd-8a19-4a9a-a426-72e50cb9e6dd", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "a3e89f70-ce2d-4665-9ad6-b850595779f0", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "2160c6bd-8a19-4a9a-a426-72e50cb9e6dd", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Communicate the event with parents and invite them to the mela", + "externalId": "IMP-3147aa-TASK10", + "description": "", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-10T15:53:31.493+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d8", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Invite parents", + "externalId": "IMP-3147aa-TASK4-1611320352811", + "description": "", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-10T15:53:31.468+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + }, + { + "_id": "be7e0147-566f-481c-9d15-9e2eb60ec7e5", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "d563818f-fd71-4119-b24d-5a122b98f3d4", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "be7e0147-566f-481c-9d15-9e2eb60ec7e5", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Do necessary arrangements for smooth functioning of the event and to make it attractive and interesting to parents", + "externalId": "IMP-3147aa-TASK11", + "description": "", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-10T15:53:31.498+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d9", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Make the arrangements", + "externalId": "IMP-3147aa-TASK5-1611320352814", + "description": "", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-10T15:53:31.471+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + }, + { + "_id": "ad68fca1-1e37-45a0-b7cc-11e93fb2c23a", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "e1d2f43f-1f0a-4167-b27b-104baf530d9f", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "ad68fca1-1e37-45a0-b7cc-11e93fb2c23a", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Make sure you collect feedback from parents after the event and reflect among the teachers to see the areas of improvement for next year.", + "externalId": "IMP-3147aa-TASK12", + "description": "", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-10T15:53:31.503+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15da", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Collect feedback after the event", + "externalId": "IMP-3147aa-TASK6-1611320352816", + "description": "", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-10T15:53:31.473+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000" + }, + { + "_id": "0cb96fa4-054d-48ed-a000-89763e1aad6f", + "createdBy": "e7719630-0457-47ca-a5ce-8190ffb34f13", + "updatedBy": "e7719630-0457-47ca-a5ce-8190ffb34f13", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "observation", + "solutionDetails": { + "_id": "600b21227ea68a7ed9278868", + "isReusable": false, + "externalId": "AP-TEST-PROGRAM-3.6.5-OBS-IMP-PROJECT-2-BEO", + "name": "AP-TEST-PROGRAM-3.6.5-OBS-IMP-PROJECT-2-BEO", + "programId": "600ab53cc7de076e6f993724", + "type": "observation", + "subType": "block", + "allowMultipleAssessemts": false, + "isRubricDriven": false, + "criteriaLevelReport": "", + "scoringSystem": "", + "minNoOfSubmissionsRequired": 1 + }, + "name": "Observation task for BEO", + "externalId": "OT-3.6.5-BEO", + "description": "Observation task for BEO", + "updatedAt": "2021-02-01T09:47:26.174+0000", + "createdAt": "2020-12-01T17:06:56.999+0000", + "isDeletable": false, + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-01T09:47:26.174+0000", + "observationInformation": { + "entityId": "d8a34179-d925-4bca-a320-3d8c7cbcffa4", + "programId": "600ab53cc7de076e6f993724", + "solutionId": "600b21227ea68a7ed9278868" + } + } + ], + "updatedBy": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "rootOrganisations": ["0126796199493140480"], + "learningResources": [ + { + "name": "Examprep_10EM_ps_cha1_Q3", + "id": "do_31268582767737241615189", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31268582767737241615189" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q2", + "id": "do_31269107959395942417491", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269107959395942417491" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "description": "Come See Our School!- Parent Mela", + "title": "Come See Our School!- Parent Mela", + "metaInformation": { + "rationale": "", + "primaryAudience": ["Community"], + "goal": "Organizing the Parent Mela in the school in order to make better community reach", + "duration": "At the end of every quarter", + "successIndicators": "", + "risks": "", + "approaches": "" + }, + "updatedAt": "2023-07-12T12:01:15.790+0000", + "createdAt": "2021-02-01T09:47:26.161+0000", + "__v": 0, + "solutionId": "600acbe7c7de076e6f9950a4", + "solutionExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "programId": "600ab53cc7de076e6f993724", + "programExternalId": "AP-TEST-PROGRAM-3.6.5", + "projectTemplateId": "600acc20a0cc3e4909f91f68", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "taskReport": { + "total": 7, + "notStarted": 7 + }, + "isAPrivateProgram": false, + "programInformation": { + "_id": "600ab53cc7de076e6f993724", + "externalId": "AP-TEST-PROGRAM-3.6.5", + "description": "AP Test program for release 3.6.5", + "name": "AP-TEST-PROGRAM-3.6.5" + }, + "solutionInformation": { + "_id": "600acbe7c7de076e6f9950a4", + "externalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-BEO", + "description": "Description of Come See Our School!- Parent Mela", + "name": "Come See Our School!- Parent Mela" + }, + "entityInformation": { + "externalId": "282316", + "name": "B.N.KANDRIGA", + "district": "D_AP-D013", + "districtId": "5fd098e2e049735a86b748b8", + "state": "AP", + "_id": "d8a34179-d925-4bca-a320-3d8c7cbcffa4", + "entityType": "block", + "entityTypeId": "5f32d8228e0dc8312404056b", + "registryDetails": { + "locationId": "d8a34179-d925-4bca-a320-3d8c7cbcffa4", + "code": "282316", + "lastUpdatedAt": "2021-01-27T13:12:17.009Z" + }, + "hierarchy": [ + { + "code": "2823", + "name": "Chittoor", + "id": "b5c35cfc-6c1e-4266-94ef-a425c43c7f4e", + "type": "district", + "parentId": "bc75cc99-9205-463e-a722-5326857838f8" + }, + { + "code": "28", + "name": "Andhra Pradesh", + "id": "bc75cc99-9205-463e-a722-5326857838f8", + "type": "state" + } + ] + }, + "entityId": "d8a34179-d925-4bca-a320-3d8c7cbcffa4", + "lastDownloadedAt": "2021-02-01T09:47:26.180+0000", + "appInformation": { + "appName": "DIKSHA", + "appVersion": "86" + }, + "hasAcceptedTAndC": false, + "userProfile": { + "webPages": null, + "maskedPhone": null, + "tcStatus": null, + "loginId": null, + "subject": null, + "channel": "dikshapreprodcustodian", + "profileUserTypes": [ + { + "type": "administrator", + "subType": "chm" + } + ], + "language": null, + "updatedDate": "2021-02-03 07:43:13:773+0000", + "password": null, + "managedBy": null, + "flagsValue": 2, + "id": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "recoveryEmail": "", + "identifier": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "thumbnail": null, + "profileVisibility": null, + "updatedBy": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "accesscode": null, + "externalIds": [], + "registryId": null, + "roleList": [ + { + "name": "Book Creator", + "id": "BOOK_CREATOR" + }, + { + "name": "Membership Management", + "id": "MEMBERSHIP_MANAGEMENT" + }, + { + "name": "Flag Reviewer", + "id": "FLAG_REVIEWER" + }, + { + "name": "Report Viewer", + "id": "REPORT_VIEWER" + }, + { + "name": "Program Manager", + "id": "PROGRAM_MANAGER" + }, + { + "name": "Program Designer", + "id": "PROGRAM_DESIGNER" + }, + { + "name": "System Administration", + "id": "SYSTEM_ADMINISTRATION" + }, + { + "name": "Content Curation", + "id": "CONTENT_CURATION" + }, + { + "name": "Book Reviewer", + "id": "BOOK_REVIEWER" + }, + { + "name": "Content Creator", + "id": "CONTENT_CREATOR" + }, + { + "name": "Org Management", + "id": "ORG_MANAGEMENT" + }, + { + "name": "Course Admin", + "id": "COURSE_ADMIN" + }, + { + "name": "Org Moderator", + "id": "ORG_MODERATOR" + }, + { + "name": "Public", + "id": "PUBLIC" + }, + { + "name": "Admin", + "id": "ADMIN" + }, + { + "name": "Course Mentor", + "id": "COURSE_MENTOR" + }, + { + "name": "Content Reviewer", + "id": "CONTENT_REVIEWER" + }, + { + "name": "Report Admin", + "id": "REPORT_ADMIN" + }, + { + "name": "Org Admin", + "id": "ORG_ADMIN" + } + ], + "rootOrgId": "0126796199493140480", + "prevUsedEmail": "", + "firstName": "smith2", + "tncAcceptedOn": 1610945494371.0, + "allTncAccepted": {}, + "profileDetails": null, + "phone": "", + "dob": null, + "grade": null, + "currentLoginTime": null, + "userType": "administrator", + "status": 1, + "lastName": "", + "tncLatestVersion": "v12", + "gender": null, + "prevUsedPhone": "", + "stateValidated": false, + "encEmail": "dcXWh0a/IoZzf0BBo5YDesOQpg7YRsDDKJgzfiiKU1h5HUNPlEdrbYgQ6JBFa90WEd2tj0l4QKD9\nk+2W3uL5PE9KY9CSOe31SGfXFLfHPU+S1cV3v0vYkBPcrmgb2jY3T6a+wzaAmCWueMEdPmZuRg==", + "isDeleted": false, + "organisations": [ + { + "organisationId": "0126796199493140480", + "approvedBy": null, + "channel": "dikshapreprodcustodian", + "updatedDate": null, + "approvaldate": null, + "isSystemUpload": false, + "isDeleted": false, + "id": "0131968698566574080", + "isApproved": null, + "orgjoindate": "2021-01-18 04:50:58:065+0000", + "isSelfDeclaration": true, + "updatedBy": null, + "orgName": "Staging Custodian Organization", + "addedByName": null, + "addedBy": null, + "associationType": 2, + "locationIds": [ + "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf", + "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + ], + "orgLocation": [ + { + "type": "state", + "id": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf" + }, + { + "type": "district", + "id": "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + } + ], + "externalId": "101010", + "userId": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "isSchool": false, + "hashTagId": "0126796199493140480", + "isSSO": false, + "isRejected": null, + "locations": [ + { + "code": "29", + "name": "Karnataka", + "id": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf", + "type": "state", + "parentId": null + }, + { + "code": "2901", + "name": "BELAGAVI", + "id": "8250d58d-f1a2-4397-bfd3-b2e688ba7141", + "type": "district", + "parentId": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf" + } + ], + "position": null, + "orgLeftDate": null + } + ], + "provider": null, + "countryCode": null, + "tncLatestVersionUrl": "https://sunbirdstagingpublic.blob.core.windows.net/termsandcondtions/terms-and-conditions-v12.html", + "maskedEmail": "sm****@yopmail.com", + "tempPassword": null, + "email": "sm****@yopmail.com", + "rootOrg": { + "dateTime": null, + "preferredLanguage": null, + "keys": {}, + "organisationSubType": null, + "channel": "dikshapreprodcustodian", + "approvedBy": null, + "description": "Pre-prod Custodian Organization", + "updatedDate": "2022-02-18 09:50:42:752+0000", + "organisationType": 5, + "addressId": null, + "orgType": null, + "isTenant": true, + "provider": null, + "locationId": null, + "orgCode": null, + "theme": null, + "id": "0126796199493140480", + "communityId": null, + "isApproved": null, + "isBoard": true, + "email": null, + "slug": "dikshapreprodcustodian", + "isSSOEnabled": null, + "thumbnail": null, + "orgName": "Staging Custodian Organization", + "updatedBy": null, + "locationIds": [ + "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf", + "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + ], + "externalId": "101010", + "orgLocation": [ + { + "type": "state", + "id": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf" + }, + { + "type": "district", + "id": "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + } + ], + "isRootOrg": true, + "rootOrgId": "0126796199493140480", + "imgUrl": null, + "approvedDate": null, + "homeUrl": null, + "orgTypeId": null, + "isDefault": null, + "createdDate": "2019-01-18 09:48:13:428+0000", + "createdBy": "system", + "parentOrgId": null, + "hashTagId": "0126796199493140480", + "noOfMembers": null, + "status": 1 + }, + "phoneVerified": true, + "profileSummary": null, + "tcUpdatedDate": null, + "userLocations": [ + { + "code": "2823", + "name": "CHITTOOR", + "id": "b5c35cfc-6c1e-4266-94ef-a425c43c7f4e", + "type": "district", + "parentId": "bc75cc99-9205-463e-a722-5326857838f8" + }, + { + "code": "28", + "name": "Andhra Pradesh", + "id": "bc75cc99-9205-463e-a722-5326857838f8", + "type": "state", + "parentId": null + }, + { + "code": "282316", + "name": "B.N.KANDRIGA", + "id": "d8a34179-d925-4bca-a320-3d8c7cbcffa4", + "type": "block", + "parentId": "b5c35cfc-6c1e-4266-94ef-a425c43c7f4e" + } + ], + "recoveryPhone": "******1076", + "avatar": null, + "userName": "smith2", + "userId": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "userSubType": "chm", + "declarations": [ + { + "persona": "default", + "errorType": null, + "orgId": "12765997661519872117", + "status": "SUBMITTED", + "info": { + "declared-email": "smith2@yopmail.com", + "declared-ext-id": "123", + "declared-school-name": "A.P.T.W.E.M..R SCHOOL", + "declared-school-udise-code": "28231601515" + } + }, + { + "persona": "default", + "errorType": null, + "orgId": "do_213199093633138688144", + "status": null, + "info": {} + } + ], + "promptTnC": true, + "emailVerified": true, + "lastLoginTime": 0, + "createdDate": "2021-01-18 04:50:57:268+0000", + "framework": { + "board": ["IGOT-Health"], + "gradeLevel": ["Doctors", "Nurses"], + "id": ["igot_health"], + "medium": ["English", "Hindi"] + }, + "createdBy": null, + "profileUserType": { + "type": "administrator", + "subType": "chm" + }, + "encPhone": "", + "location": null, + "tncAcceptedVersion": "3.5.0" + } + }, + { + "_id": "6018ef65879c09505d77fc3d", + "userId": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "userRole": "DEO", + "createdFor": ["0126796199493140480", "01275630154475110432564"], + "status": "started", + "isDeleted": false, + "categories": [ + { + "_id": "5fcfa9a2457d6055e33843f0", + "name": "Students", + "externalId": "students" + }, + { + "_id": "5fcfa9a2457d6055e33843f1", + "name": "Infrastructure", + "externalId": "infrastructure" + }, + { + "_id": "5fcfa9a2457d6055e33843f2", + "name": "Community", + "externalId": "community" + } + ], + "createdBy": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "tasks": [ + { + "_id": "61b9c72a-731b-4970-b715-0c1e928a86fb", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "9cecd670-d1e9-46c9-9987-d2540953edc4", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "61b9c72a-731b-4970-b715-0c1e928a86fb", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Look for videos and case studies which capture the parent mela or parent meeting conducted in different schools. Focus on the ideas being used and themes being selected.", + "externalId": "IMP-3147aa-TASK7", + "description": "", + "updatedAt": "2021-02-02T06:21:25.075+0000", + "createdAt": "2020-12-10T15:53:31.476+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d5", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.075+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Look for samples of parent mela/ excitement building parent meeting from different schools", + "externalId": "IMP-3147aa-TASK1-1611320417509", + "description": "", + "updatedAt": "2021-02-02T06:21:25.075+0000", + "createdAt": "2020-12-10T15:53:31.460+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.075+0000" + }, + { + "_id": "a2cad0dd-5c7b-4848-af70-155da9277744", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "985b1846-302d-4988-ab0e-a78acb310b26", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "a2cad0dd-5c7b-4848-af70-155da9277744", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "-Meeting with teachers to discuss the importance and role of parent mela in improving community engagement in the school.", + "externalId": "IMP-3147aa-TASK8", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.481+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d6", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + }, + { + "_id": "e746fd95-6cbe-415c-bfce-e4de82d0b879", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "a2cad0dd-5c7b-4848-af70-155da9277744", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "-Discuss stories from other schools.", + "externalId": "IMP-3147aa-TASK13", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.509+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d6", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + }, + { + "_id": "aaf8bf9e-31d0-4b83-aac6-aaaeebc75b49", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "a2cad0dd-5c7b-4848-af70-155da9277744", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "- Form a committee among teachers to plan and facilitate the mela along with the school leader.", + "externalId": "IMP-3147aa-TASK14", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.521+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d6", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Form a parent mela committee among the teachers", + "externalId": "IMP-3147aa-TASK2-1611320417513", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.463+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + }, + { + "_id": "0577f2c4-93f2-49a9-94d7-e4dcee92bf01", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "eacbca31-eebe-40e0-88dd-07069f16c5ec", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "0577f2c4-93f2-49a9-94d7-e4dcee92bf01", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Finalize the themes and activities for the mela. This could be taken borrowed from other schools or decided by the teachers through brainstorming. \nFinalize the dates for the same", + "externalId": "IMP-3147aa-TASK9", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.487+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d7", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Planning for the mela", + "externalId": "IMP-3147aa-TASK3-1611320417515", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.465+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + }, + { + "_id": "dc310831-7c65-4afc-9c8b-1a7dd63c08ad", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "6eb049b6-f1dd-49a4-8130-ea839415784c", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "dc310831-7c65-4afc-9c8b-1a7dd63c08ad", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Communicate the event with parents and invite them to the mela", + "externalId": "IMP-3147aa-TASK10", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.493+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d8", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Invite parents", + "externalId": "IMP-3147aa-TASK4-1611320417519", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.468+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + }, + { + "_id": "c166d100-fc88-40bf-a96d-07f9c95e55c9", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "428a8310-b22f-4780-998a-aa0fc4f05fed", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "c166d100-fc88-40bf-a96d-07f9c95e55c9", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Do necessary arrangements for smooth functioning of the event and to make it attractive and interesting to parents", + "externalId": "IMP-3147aa-TASK11", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.498+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15d9", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Make the arrangements", + "externalId": "IMP-3147aa-TASK5-1611320417521", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.471+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + }, + { + "_id": "912e969e-82dc-4081-920a-828189b75dd6", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "isDeletable": true, + "taskSequence": [], + "children": [ + { + "_id": "6c0e3c7f-003c-4771-b199-6a2ddcd96c28", + "createdBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "updatedBy": "140558b9-7df4-4993-be3c-31eb8b9ca368", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [ + { + "operator": "===", + "_id": "912e969e-82dc-4081-920a-828189b75dd6", + "value": "started" + } + ], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "simple", + "projectTemplateId": "5fd21654e4d17b4af8aa6f7c", + "name": "Make sure you collect feedback from parents after the event and reflect among the teachers to see the areas of improvement for next year.", + "externalId": "IMP-3147aa-TASK12", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.503+0000", + "__v": 0, + "parentId": "5fd2447b1233354b094f15da", + "isDeletable": true, + "projectTemplateExternalId": "IMP-3147aa", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + } + ], + "visibleIf": [], + "hasSubTasks": true, + "learningResources": [ + { + "name": "MOVEMENTS", + "id": "do_3128850456266506241713", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128850456266506241713" + }, + { + "name": "ELECTRICITY", + "id": "do_3128848863878676481659", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_3128848863878676481659" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "type": "content", + "name": "Collect feedback after the event", + "externalId": "IMP-3147aa-TASK6-1611320417523", + "description": "", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-10T15:53:31.473+0000", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000" + }, + { + "_id": "7065398a-20fd-46e7-9012-67a14a38066e", + "createdBy": "e7719630-0457-47ca-a5ce-8190ffb34f13", + "updatedBy": "e7719630-0457-47ca-a5ce-8190ffb34f13", + "isDeleted": false, + "taskSequence": [], + "children": [], + "visibleIf": [], + "hasSubTasks": false, + "learningResources": [], + "deleted": false, + "type": "observation", + "solutionDetails": { + "_id": "600b21c57ea68a7ed9278873", + "isReusable": false, + "externalId": "AP-TEST-PROGRAM-3.6.5-OBS-IMP-PROJECT-2-DEO", + "name": "AP-TEST-PROGRAM-3.6.5-OBS-IMP-PROJECT-2-DEO", + "programId": "600ab53cc7de076e6f993724", + "type": "observation", + "subType": "district", + "allowMultipleAssessemts": false, + "isRubricDriven": false, + "criteriaLevelReport": "", + "scoringSystem": "", + "minNoOfSubmissionsRequired": 1 + }, + "name": "Observation task for DEO", + "externalId": "OT-3.6.5-DEO", + "description": "Observation task for DEO", + "updatedAt": "2021-02-02T06:21:25.076+0000", + "createdAt": "2020-12-01T17:06:56.999+0000", + "isDeletable": false, + "status": "notStarted", + "isImportedFromLibrary": false, + "syncedAt": "2021-02-02T06:21:25.076+0000", + "observationInformation": { + "entityId": "732b83e7-cf4f-401c-a374-db1d45644b3b", + "programId": "600ab53cc7de076e6f993724", + "solutionId": "600b21c57ea68a7ed9278873", + "observationId": "6033a1f81bfad8731adc6dc7" + }, + "submissions": [] + } + ], + "updatedBy": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "rootOrganisations": ["0126796199493140480"], + "learningResources": [ + { + "name": "Examprep_10EM_ps_cha1_Q3", + "id": "do_31268582767737241615189", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31268582767737241615189" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q2", + "id": "do_31269107959395942417491", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269107959395942417491" + }, + { + "name": "Examprep_10tm_ps_cha 11-Q3", + "id": "do_31269108472948326417493", + "app": "diksha", + "link": "https://staging.sunbirded.org/resources/play/content/do_31269108472948326417493" + } + ], + "deleted": false, + "description": "Come See Our School!- Parent Mela", + "title": "Come See Our School!- Parent Mela", + "metaInformation": { + "rationale": "", + "primaryAudience": ["Community"], + "goal": "Organizing the Parent Mela in the school in order to make better community reach", + "duration": "At the end of every quarter", + "successIndicators": "", + "risks": "", + "approaches": "" + }, + "updatedAt": "2021-09-30T16:07:05.334+0000", + "createdAt": "2021-02-02T06:21:25.056+0000", + "__v": 0, + "solutionId": "600acc42c7de076e6f995147", + "solutionExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "programId": "600ab53cc7de076e6f993724", + "programExternalId": "AP-TEST-PROGRAM-3.6.5", + "projectTemplateId": "600acc61a0cc3e4909f91f80", + "projectTemplateExternalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "taskReport": { + "total": 7, + "notStarted": 7 + }, + "isAPrivateProgram": false, + "programInformation": { + "_id": "600ab53cc7de076e6f993724", + "externalId": "AP-TEST-PROGRAM-3.6.5", + "description": "AP Test program for release 3.6.5", + "name": "AP-TEST-PROGRAM-3.6.5" + }, + "solutionInformation": { + "_id": "600acc42c7de076e6f995147", + "externalId": "AP-TEST-PROGRAM-3.6.5-IMP-PROJECT-1-DEO", + "description": "Description of Come See Our School!- Parent Mela", + "name": "Come See Our School!- Parent Mela" + }, + "appInformation": { + "appName": "DIKSHA", + "appVersion": "86" + }, + "entityInformation": { + "externalId": "2820", + "name": "KADAPA", + "region": "", + "districtId": "2820", + "state": "AP", + "_id": "732b83e7-cf4f-401c-a374-db1d45644b3b", + "entityType": "district", + "entityTypeId": "5f32d8228e0dc8312404056c", + "registryDetails": { + "locationId": "732b83e7-cf4f-401c-a374-db1d45644b3b", + "code": "2820", + "lastUpdatedAt": "2021-01-27T13:08:55.994Z" + }, + "hierarchy": [ + { + "code": "28", + "name": "Andhra Pradesh", + "id": "bc75cc99-9205-463e-a722-5326857838f8", + "type": "state" + } + ] + }, + "entityId": "732b83e7-cf4f-401c-a374-db1d45644b3b", + "lastDownloadedAt": "2021-02-02T06:21:25.085+0000", + "lastSync": "2021-02-11T06:59:24.269+0000", + "syncedAt": "2021-02-11T06:59:24.269+0000", + "hasAcceptedTAndC": false, + "userRoleInformation": { + "district": "aecac7ab-15e4-45c9-ac7b-d716444cd652", + "state": "bc75cc99-9205-463e-a722-5326857838f8", + "block": "f6d40b8a-3ba0-4e3b-b7f5-2586b69122f6", + "school": "28110502802", + "role": "HM" + }, + "userProfile": { + "webPages": null, + "maskedPhone": null, + "tcStatus": null, + "loginId": null, + "subject": null, + "channel": "dikshapreprodcustodian", + "profileUserTypes": [ + { + "subType": "hm", + "type": "administrator" + } + ], + "language": null, + "updatedDate": "2021-04-21 13:06:11:740+0000", + "password": null, + "managedBy": null, + "flagsValue": 2, + "id": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "recoveryEmail": "", + "identifier": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "thumbnail": null, + "profileVisibility": null, + "updatedBy": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "accesscode": null, + "externalIds": [], + "registryId": null, + "roleList": [ + { + "name": "Book Creator", + "id": "BOOK_CREATOR" + }, + { + "name": "Membership Management", + "id": "MEMBERSHIP_MANAGEMENT" + }, + { + "name": "Flag Reviewer", + "id": "FLAG_REVIEWER" + }, + { + "name": "Report Viewer", + "id": "REPORT_VIEWER" + }, + { + "name": "Program Manager", + "id": "PROGRAM_MANAGER" + }, + { + "name": "Program Designer", + "id": "PROGRAM_DESIGNER" + }, + { + "name": "System Administration", + "id": "SYSTEM_ADMINISTRATION" + }, + { + "name": "Content Curation", + "id": "CONTENT_CURATION" + }, + { + "name": "Book Reviewer", + "id": "BOOK_REVIEWER" + }, + { + "name": "Content Creator", + "id": "CONTENT_CREATOR" + }, + { + "name": "Org Management", + "id": "ORG_MANAGEMENT" + }, + { + "name": "Course Admin", + "id": "COURSE_ADMIN" + }, + { + "name": "Org Moderator", + "id": "ORG_MODERATOR" + }, + { + "name": "Public", + "id": "PUBLIC" + }, + { + "name": "Admin", + "id": "ADMIN" + }, + { + "name": "Course Mentor", + "id": "COURSE_MENTOR" + }, + { + "name": "Content Reviewer", + "id": "CONTENT_REVIEWER" + }, + { + "name": "Report Admin", + "id": "REPORT_ADMIN" + }, + { + "name": "Org Admin", + "id": "ORG_ADMIN" + } + ], + "rootOrgId": "0126796199493140480", + "prevUsedEmail": "", + "firstName": "Rejneesh R", + "isMinor": false, + "tncAcceptedOn": 1611404969636.0, + "allTncAccepted": { + "groupsTnc": { + "tncAcceptedOn": "2021-02-16 09:08:46:874+0000", + "version": "3.5.0" + } + }, + "profileDetails": null, + "phone": "", + "dob": "1993-12-31", + "grade": null, + "currentLoginTime": null, + "userType": "administrator", + "status": 1, + "lastName": "", + "tncLatestVersion": "v12", + "gender": null, + "prevUsedPhone": "", + "stateValidated": false, + "encEmail": "1uohqqrxzkWsYjwXZtNnzHSR60U3iie3psyNAEaEQSqQUh0tAAwJU4iP3wEWbvXsLbm2FmQHebSZ\nZtJE4nop9d6nYo0pJK3k3v6YdFSJasNIMf6JTlqlIXMa0/gYdzBBT6a+wzaAmCWueMEdPmZuRg==", + "isDeleted": false, + "organisations": [ + { + "organisationId": "0126796199493140480", + "approvedBy": null, + "channel": "dikshapreprodcustodian", + "updatedDate": null, + "approvaldate": null, + "isSystemUpload": false, + "isDeleted": false, + "id": "01319344873463808077", + "isApproved": null, + "orgjoindate": "2021-01-13 08:47:58:166+0000", + "isSelfDeclaration": true, + "updatedBy": null, + "orgName": "Staging Custodian Organization", + "addedByName": null, + "addedBy": null, + "associationType": 2, + "locationIds": [ + "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf", + "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + ], + "orgLocation": [ + { + "type": "state", + "id": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf" + }, + { + "type": "district", + "id": "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + } + ], + "externalId": "101010", + "userId": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "isSchool": false, + "hashTagId": "0126796199493140480", + "isSSO": false, + "isRejected": null, + "locations": [ + { + "code": "29", + "name": "Karnataka", + "id": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf", + "type": "state", + "parentId": null + }, + { + "code": "2901", + "name": "BELAGAVI", + "id": "8250d58d-f1a2-4397-bfd3-b2e688ba7141", + "type": "district", + "parentId": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf" + } + ], + "position": null, + "orgLeftDate": null + }, + { + "organisationId": "012756293600911360616", + "approvedBy": null, + "channel": "apekx", + "updatedDate": null, + "approvaldate": null, + "isSystemUpload": false, + "isDeleted": false, + "id": "01326294083861708862", + "isApproved": false, + "orgjoindate": "2021-04-21 13:06:11:752+0000", + "isSelfDeclaration": true, + "updatedBy": null, + "orgName": "MPPS BATHUVA", + "addedByName": null, + "addedBy": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "associationType": 2, + "locationIds": [ + "bc75cc99-9205-463e-a722-5326857838f8", + "8ac1efe9-0415-4313-89ef-884e1c8eee34", + "cb635528-0c07-49c7-94ff-2e64ccf7c1af" + ], + "orgLocation": [ + { + "type": "state", + "id": "bc75cc99-9205-463e-a722-5326857838f8" + }, + { + "type": "district", + "id": "8ac1efe9-0415-4313-89ef-884e1c8eee34" + }, + { + "type": "block", + "id": "cb635528-0c07-49c7-94ff-2e64ccf7c1af" + } + ], + "externalId": "28110502802", + "userId": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "isSchool": true, + "hashTagId": "012756293600911360616", + "isSSO": false, + "isRejected": false, + "locations": [ + { + "code": "28", + "name": "Andhra Pradesh", + "id": "bc75cc99-9205-463e-a722-5326857838f8", + "type": "state", + "parentId": null + }, + { + "code": "2811", + "name": "SRIKAKULAM", + "id": "8ac1efe9-0415-4313-89ef-884e1c8eee34", + "type": "district", + "parentId": "bc75cc99-9205-463e-a722-5326857838f8" + }, + { + "code": "281105", + "name": "G.SIGADAM", + "id": "cb635528-0c07-49c7-94ff-2e64ccf7c1af", + "type": "block", + "parentId": "8ac1efe9-0415-4313-89ef-884e1c8eee34" + } + ], + "position": null, + "orgLeftDate": null + } + ], + "provider": null, + "countryCode": "+91", + "tncLatestVersionUrl": "https://sunbirdstagingpublic.blob.core.windows.net/termsandcondtions/terms-and-conditions-v12.html", + "maskedEmail": "re******@tunerlabs.com", + "tempPassword": null, + "email": "re******@tunerlabs.com", + "rootOrg": { + "dateTime": null, + "preferredLanguage": null, + "keys": {}, + "organisationSubType": null, + "channel": "dikshapreprodcustodian", + "approvedBy": null, + "description": "Pre-prod Custodian Organization", + "updatedDate": "2022-02-18 09:50:42:752+0000", + "organisationType": 5, + "addressId": null, + "orgType": null, + "isTenant": true, + "provider": null, + "locationId": null, + "orgCode": null, + "theme": null, + "id": "0126796199493140480", + "communityId": null, + "isApproved": null, + "isBoard": true, + "email": null, + "slug": "dikshapreprodcustodian", + "isSSOEnabled": null, + "thumbnail": null, + "orgName": "Staging Custodian Organization", + "updatedBy": null, + "locationIds": [ + "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf", + "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + ], + "externalId": "101010", + "orgLocation": [ + { + "type": "state", + "id": "027f81d8-0a2c-4fc6-96ac-59fe4cea3abf" + }, + { + "type": "district", + "id": "8250d58d-f1a2-4397-bfd3-b2e688ba7141" + } + ], + "isRootOrg": true, + "rootOrgId": "0126796199493140480", + "imgUrl": null, + "approvedDate": null, + "homeUrl": null, + "orgTypeId": null, + "isDefault": null, + "createdDate": "2019-01-18 09:48:13:428+0000", + "createdBy": "system", + "parentOrgId": null, + "hashTagId": "0126796199493140480", + "noOfMembers": null, + "status": 1 + }, + "phoneVerified": true, + "profileSummary": null, + "tcUpdatedDate": null, + "userLocations": [ + { + "code": "2814", + "name": "EAST GODAVARI", + "id": "aecac7ab-15e4-45c9-ac7b-d716444cd652", + "type": "district", + "parentId": "bc75cc99-9205-463e-a722-5326857838f8" + }, + { + "code": "28", + "name": "Andhra Pradesh", + "id": "bc75cc99-9205-463e-a722-5326857838f8", + "type": "state", + "parentId": null + }, + { + "code": "281454", + "name": "AMALAPURAM", + "id": "f6d40b8a-3ba0-4e3b-b7f5-2586b69122f6", + "type": "block", + "parentId": "aecac7ab-15e4-45c9-ac7b-d716444cd652" + }, + { + "code": "28110502802", + "name": "MPPS BATHUVA", + "id": "012756293600911360616", + "type": "school", + "parentId": "" + } + ], + "recoveryPhone": "", + "avatar": null, + "userName": "rejneeshr_pt83", + "userId": "44e4c0a0-e96c-4e3e-9294-33713aebdf70", + "userSubType": "hm", + "declarations": [ + { + "persona": "default", + "errorType": null, + "orgId": "0126796199493140480", + "status": null, + "info": {} + }, + { + "persona": "default", + "errorType": null, + "orgId": "do_2130569914095452161188", + "status": null, + "info": {} + } + ], + "promptTnC": true, + "emailVerified": true, + "lastLoginTime": 0, + "createdDate": "2021-01-13 08:47:58:140+0000", + "framework": { + "board": ["State (Andhra Pradesh"], + "id": ["ap_k-12_1"] + }, + "createdBy": null, + "profileUserType": { + "subType": "hm", + "type": "administrator" + }, + "encPhone": null, + "location": null, + "tncAcceptedVersion": "3.5.0" + } + } +] diff --git a/DBSchema/solutions.json b/DBSchema/solutions.json new file mode 100644 index 00000000..f68a675f --- /dev/null +++ b/DBSchema/solutions.json @@ -0,0 +1,469 @@ +[ + { + "_id" : "5f34ade5585244939f89f8f5", + "resourceType" : [ + "Observations Framework" + ], + "language" : [ + "English" + ], + "keywords" : [ + "Framework", + "Observation" + ], + "concepts" : [ + + ], + "createdFor" : [ + "0123221617357783046602" + ], + "themes" : [ + { + "type" : "theme", + "label" : "theme", + "name" : "Observation Theme", + "externalId" : "OB", + "weightage" : 100, + "criteria" : [ + { + "criteriaId" : "5f34ade5585244939f89f8f2", + "weightage" : 33.333333333333336 + }, + { + "criteriaId" : "5f34ade5585244939f89f8f3", + "weightage" : 33.333333333333336 + }, + { + "criteriaId" : "5f34ade5585244939f89f8f4", + "weightage" : 33.333333333333336 + } + ] + } + ], + "flattenedThemes" : [ + + ], + "entities" : [ + + ], + "registry" : [ + + ], + "isRubricDriven" : false, + "enableQuestionReadOut" : false, + "captureGpsLocationAtQuestionLevel" : false, + "isAPrivateProgram" : false, + "allowMultipleAssessemts" : false, + "isDeleted" : false, + "rootOrganisations" : [ + "0123221617357783046602" + ], + "deleted" : false, + "externalId" : "cbd074fa-dd11-11ea-a3bf-000d3af02677-OBSERVATION-TEMPLATE", + "name" : "MH01-Mantra4Change-APSWREIS School Leader Feedback", + "description" : "Feedback on Mantra4Change engagement with APSWREIS school leaders", + "author" : "19d81ef7-36ce-41fe-ae2d-c8365d977be4", + "levelToScoreMapping" : { + "L1" : { + "points" : 100, + "label" : "Good" + } + }, + "scoringSystem" : null, + "noOfRatingLevels" : 1, + "entityTypeId" : "5f32d8228e0dc83124040567", + "entityType" : "school", + "type" : "observation", + "subType" : "school", + "updatedBy" : "INITIALIZE", + "createdAt" : "2020-08-13T03:05:09.183+0000", + "updatedAt" : "2020-08-13T03:05:09.236+0000", + "frameworkId" : "5f34ade5ec065458d5c9d4ef", + "frameworkExternalId" : "cbd074fa-dd11-11ea-a3bf-000d3af02677", + "isReusable" : true, + "__v" : 0, + "evidenceMethods" : { + "OB" : { + "externalId" : "OB", + "tip" : null, + "name" : "Observation", + "description" : null, + "modeOfCollection" : "onfield", + "canBeNotApplicable" : false, + "notApplicable" : false, + "canBeNotAllowed" : false, + "remarks" : null + } + }, + "isTempObTest" : "observationAutomation", + "sections" : { + "S1" : "Observation Questions" + }, + "status" : "active", + "questionSequenceByEcm" : { + "OB" : { + "S1" : [ + "SLFB001_1597287896354", + "SLFB002_1597287896354", + "SLFB003_1597287896354", + "SLFB004_1597287896354", + "SLFB005_1597287896354", + "SLFB006_1597287896354", + "SLFB007_1597287896354", + "SLFB008_1597287896354", + "SLFB009_1597287896354", + "SLFB010_1597287896354", + "SLFB011_1597287896354", + "SLFB012_1597287896354", + "SLFB013_1597287896354", + "SLFB014_1597287896354", + "SLFB015_1597287896354", + "SLFB016_1597287896354", + "SLFB017_1597287896354" + ] + } + }, + "minNoOfSubmissionsRequired" : 1 + }, + { + "_id" : "5fa278c72dbd4b755b88e637", + "resourceType" : [ + "Survey Solution" + ], + "language" : [ + "English" + ], + "keywords" : [ + "Survey" + ], + "concepts" : [ + + ], + "createdFor" : [ + + ], + "themes" : [ + { + "type" : "theme", + "label" : "theme", + "externalId" : "SF", + "name" : "Survey and Feedback", + "weightage" : 0, + "criteria" : [ + { + "criteriaId" : "5fa278c72dbd4b755b88e636", + "weightage" : 0 + } + ] + } + ], + "flattenedThemes" : [ + + ], + "entities" : [ + + ], + "registry" : [ + + ], + "isRubricDriven" : false, + "enableQuestionReadOut" : false, + "captureGpsLocationAtQuestionLevel" : false, + "isAPrivateProgram" : false, + "allowMultipleAssessemts" : false, + "isDeleted" : false, + "rootOrganisations" : [ + + ], + "deleted" : false, + "type" : "survey", + "subType" : "survey", + "name" : "Diksha test survey ", + "externalId" : "cdcc3246-1e82-11eb-a3bf-000d3af02677-SURVEY-TEMPLATE", + "description" : "Diksha test survey via genie", + "linkTitle" : "", + "linkUrl" : "", + "author" : "86d2d978-5b20-4453-8a76-82b5a4c728c9", + "isReusable" : true, + "status" : "active", + "startDate" : "2020-11-04T09:47:51.233+0000", + "endDate" : "2021-11-04T09:47:51.233+0000", + "sections" : { + "SQ" : "Survey Questions" + }, + "evidenceMethods" : { + "SF" : { + "externalId" : "SF", + "name" : "Survey And Feedback", + "description" : "Survey And Feedback", + "modeOfCollection" : "", + "canBeNotApplicable" : false, + "notApplicable" : false, + "canBeNotAllowed" : false, + "remarks" : "", + "isActive" : true + } + }, + "updatedAt" : "2020-11-04T09:47:51.238+0000", + "createdAt" : "2020-11-04T09:47:51.238+0000", + "__v" : 0, + "minNoOfSubmissionsRequired" : 1 + }, + { + "_id" : "61558fec27e9cd00077530e4", + "scope" : { + "entityType" : "state", + "entityTypeId" : "5f32d8228e0dc8312404056e", + "roles" : [ + { + "_id" : "5f32d8238e0dc831240405a0", + "code" : "HM" + } + ], + "entities" : [ + "bc75cc99-9205-463e-a722-5326857838f8" + ] + }, + "resourceType" : [ + + ], + "language" : [ + + ], + "keywords" : [ + + ], + "concepts" : [ + + ], + "themes" : [ + + ], + "flattenedThemes" : [ + + ], + "entities" : [ + + ], + "registry" : [ + + ], + "isRubricDriven" : false, + "enableQuestionReadOut" : false, + "captureGpsLocationAtQuestionLevel" : false, + "isAPrivateProgram" : false, + "allowMultipleAssessemts" : false, + "isDeleted" : false, + "pageHeading" : "Domains", + "deleted" : false, + "name" : "Copy of Jaga july 14th test course", + "description" : "Test", + "link" : "https://staging.sunbirded.org/explore-course/course/do_2133511258201620481282", + "externalId" : "FD79-copy-of-jaga-july-14th-test-course", + "type" : "course", + "subType" : "course", + "programExternalId" : "PGM-testing_program-4.3", + "isReusable" : false, + "programId" : "61558efa27e9cd00077530b5", + "programName" : "Testing program 4.3", + "programDescription" : "Testing program 4.3", + "status" : "active", + "updatedAt" : "2021-09-30T10:28:13.717+0000", + "createdAt" : "2021-09-30T10:22:36.614+0000", + "__v" : 0, + "updatedBy" : "ec8deeb2-4ded-4fa2-ac48-023ad8298d92", + "minNoOfSubmissionsRequired" : 1 + }, + { + "_id" : "5f75c3879a3faabb16a0845f", + "resourceType" : [ + "Individual Assessment Framework" + ], + "language" : [ + "English" + ], + "keywords" : [ + "Framework", + "Assessment" + ], + "concepts" : [ + + ], + "createdFor" : [ + "0124487522476933120" + ], + "themes" : [ + { + "name" : "Theme 1", + "type" : "theme", + "label" : "theme", + "externalId" : "SL", + "weightage" : 40, + "criteria" : [ + { + "criteriaId" : "5f75c3879a3faabb16a0845c", + "weightage" : 40 + }, + { + "criteriaId" : "5f75c3879a3faabb16a0845d", + "weightage" : 40 + }, + { + "criteriaId" : "5f75c3879a3faabb16a0845a", + "weightage" : 40 + }, + { + "criteriaId" : "5f75c3879a3faabb16a0845b", + "weightage" : 40 + }, + { + "criteriaId" : "5f75c3879a3faabb16a0845e", + "weightage" : 40 + } + ] + } + ], + "flattenedThemes" : [ + + ], + "entities" : [ + + ], + "registry" : [ + + ], + "isRubricDriven" : false, + "enableQuestionReadOut" : false, + "captureGpsLocationAtQuestionLevel" : false, + "isAPrivateProgram" : false, + "allowMultipleAssessemts" : false, + "isDeleted" : false, + "rootOrganisations" : [ + + ], + "deleted" : false, + "subType" : "individual", + "type" : "assessment", + "entityType" : "schoolLeader", + "name" : "KEF - Remote teaching and learning baseline assessment for PL", + "externalId" : "KEF-RTLBS-INDIVIDUAL_ASSESSMENT-TEMPLATE", + "updatedAt" : "2020-10-01T11:54:47.738+0000", + "createdAt" : "2020-10-01T16:01:59.349+0000", + "entityTypeId" : "5f32d8228e0dc8312404056a", + "author" : "a082787f-8f8f-42f2-a706-35457ca6f1fd", + "updatedBy" : "INITIALIZE", + "description" : "This is a type of individual assessment", + "frameworkId" : "5f75b81254670074deacef1c", + "frameworkExternalId" : "KEF-RTLBS-INDIVIDUAL_ASSESSMENT", + "isReusable" : true, + "__v" : 0, + "minNoOfSubmissionsRequired" : 1 + }, + { + "_id" : "5f688f019331bf20ee36b13e", + "resourceType" : [ + "ImprovmentProject Solution" + ], + "language" : [ + "English" + ], + "keywords" : [ + "Framework", + "Improvment Project" + ], + "concepts" : [ + "" + ], + "createdFor" : [ + + ], + "registry" : [ + + ], + "type" : "improvementProject", + "subType" : "improvementProject", + "deleted" : false, + "externalId" : "f46b1ea0-fbfd-11ea-8877-65b250e90278", + "name" : "test", + "description" : "", + "author" : "", + "createdAt" : "2020-09-21T11:31:13.000+0000", + "updatedAt" : "2020-09-21T11:31:13.000+0000", + "frameworkId" : "", + "entityTypeId" : "", + "entityType" : "", + "status" : "Open", + "isDeleted" : false, + "isReusable" : false, + "parentSolutionId" : "", + "baseProjectDetails" : [ + { + "title" : "test", + "externalId" : "5bd5c4a6-0ccc-41fe-9633-d61ed5378a77", + "categories" : [ + + ], + "duration" : { + "value" : "1W", + "label" : "1 Week" + }, + "difficultyLevel" : { + "value" : "B", + "label" : "Basic" + }, + "description" : "test", + "concepts" : [ + "" + ], + "keywords" : [ + "" + ], + "status" : "published", + "isDeleted" : false, + "recommendedFor" : [ + + ], + "tasks" : [ + + ], + "createdAt" : "2020-12-08T15:18:44+00:00", + "updatedAt" : "2020-12-08T15:18:44+00:00", + "createdBy" : "SYSTEM", + "updatedBy" : "SYSTEM", + "learningResources" : [ + + ], + "isReusable" : true, + "entityType" : [ + + ], + "taskSequence" : [ + + ], + "metaInformation" : { + "supportingDocuments" : [ + "" + ], + "primaryAudience" : [ + "" + ] + }, + "_id" : "5fcf9954546a92494f2e587c" + } + ], + "programId" : "5fcf9953546a92494f2e5873", + "roles" : { + "projectManagers" : [ + + ], + "programManagers" : [ + + ], + "collaborators" : [ + "86d2d978-5b20-4453-8a76-82b5a4c728c9" + ] + }, + "__v" : 0, + "minNoOfSubmissionsRequired" : 1 + } +] \ No newline at end of file diff --git a/README.md b/README.md index 42a0b404..91dde12f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,134 @@ # ml-projects-service -ML projects Service + +This is ml-projects-services, the managed-learn component responsible for creating projects within the managed learn services. + +# Setup Guide + +## Pre-Requisite + +- Install any IDE in your system(eg: VScode etc..) +- Install nodejs from : https://nodejs.org/en/download/ +- Install mongoDB: https://docs.mongodb.com/manual/installation/ +- Install Robo 3T: ​​https://robomongo.org/ + +Basic understanding of git and github is recommended. + +- https://www.youtube.com/watch?v=RGOj5yH7evk&t=2s +- https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F + +## Setup ml-projects-services + +### Clone the service repository onto your system + +- Create a new folder where you want to clone the repository. +- Navigate to that directory using the terminal. +- Execute the git commands to clone the repository using the provided link from the code tab. + +Git link + + https://github.com/shikshalokam/ml-projects-service.git + +command to clone + + git clone https://github.com/shikshalokam/ml-projects-service.git + +### Create .env file + +Create a file named `.env` and copy the environment-specific data corresponding to that service into the `.env` file. + + # Ml project service configurations file + + APPLICATION_PORT = "3000" // Application port number + APPLICATION_ENV = "development" // Application running environment + + INTERNAL_ACCESS_TOKEN = "Fg*************yr" // Internal access token for accessing internal service APIs + + # DB + MONGODB_URL = "mongodb://localhost:27017/sl-assessment" // Mongodb connection url + + # ML Core Service + ML_CORE_SERVICE_URL = "http://ml-core-service:3000" // ML Core Service URL + + # ML Reports Service + ML_REPORTS_SERVICE_URL = "http://ml-reports-service:3000" // ML Reports Service URL + + # ML Survey Service + ML_SURVEY_SERVICE_URL = "http://ml-survey-service:3000" // ML Survey Service URL + + # OFFLINE VALIDATION + KEYCLOAK_PUBLIC_KEY_PATH = "keycloak-public-keys" // Keycloak public key path + + # KAFKA Configurations + KAFKA_COMMUNICATIONS_ON_OFF = "ON/OFF" // Kafka enable or disable communication flag + KAFKA_URL = "172.31.0.4:9092" // IP address of kafka server with port without HTTP + KAFKA_GROUP_ID = "projects" // Kafka group id + + # SUBMISSION TOPIC + SUBMISSION_TOPIC = "dev.sl.projects.submissions" // Kafka topic name for pushing projects submissions + PROJECT_SUBMISSION_TOPIC = "dev.sl.projects.submissions" // project submission topic + + # SUNBIRD LOCATION AND USER READ + USER_SERVICE_URL = "http://user-service:3000" // service used for user profile read location search are using this base url + + #service name + SERVICE_NAME = ml-project-service // ml-project service name + + # sunbird-rc service + CERTIFICATE_SERVICE_URL = http://registry-service:8081 // sunbird-RC registry service URL + + PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" // Project certificate enable or disable flag + +### Install Dependencies + +To install dependencies from a `package.json` file in Visual Studio Code, you can use the integrated terminal. Here are the steps: + +- Open the integrated terminal by going to View > Terminal or using the shortcut Ctrl+` (backtick). +- In the terminal, navigate to the directory where the package.json file is located. +- Run the command `npm install` or `yarn install`, depending on your preferred package manager. +- The package manager will read the package.json file and install all the dependencies specified in it. +- Wait for the installation process to complete. You should see progress indicators or a success message for each installed dependency. +- Once the installation is finished, the dependencies listed in the package.json file will be installed in a node_modules directory in your project. + +### Setting the keycloak + +- Create a folder on service directory named: `keycloak-public-keys` +- Inside that folder create a file `GRxxx....................xxxxx60fA` + +**for keycloak file please contact Backend Team** + +### Setup Database + +Before proceeding with these steps, ensure that you have MongoDB installed on your computer. For a graphical user interface (GUI) for MongoDB, you can choose to install Robo 3T. + +- Obtain the latest database dump from the backend team. +- Restore the database in your local environment using the following command: + + For Windows/Linux: + `mongorestore ` + + For macOS: `mongorestore -d ` + +Note: Add `` to mongoDB url in `.env` file. + +### DB Schema + +The schema serves as a blueprint for creating and maintaining the database that supports the ML projects services data storage and retrieval operations. + +![ML-Projects Service](https://ml-services-uploads.s3.ap-south-1.amazonaws.com/DBSchema/ML-Project.png) + +[Click here](https://ml-services-uploads.s3.ap-south-1.amazonaws.com/DBSchema/ML-Project.pdf) for DB schema and corresponding examples in a PDF format. + +### Postman Collection + +The ML Projects Service Postman Collection is a comprehensive resource for interacting with the ML Core Service. It includes organized endpoints, detailed documentation, and example workflows, providing a valuable reference for developers. Leverage this collection to enhance productivity and collaboration in ML Services. + +[Click here](https://documenter.getpostman.com/view/7997930/2s946chuaT) + +## IMPORTANT: + +Always work on branches. **Never make changes to master**. + +Creating a branch from master. + +For more information on git you can use : + https://education.github.com/git-cheat-sheet-education.pdf From 36d3172002b91943e64857ef741185517cafb8fb Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 2 Nov 2023 15:30:36 +0530 Subject: [PATCH 314/373] Saving changes for User DMS --- config/kafka.js | 127 +- controllers/v1/userProjects.js | 891 +-- databaseQueries/projects.js | 190 +- generics/kafka/consumers/submissions.js | 44 +- generics/kafka/consumers/userDMS.js | 55 + generics/kafka/producers.js | 177 +- generics/middleware/authenticator.js | 161 +- module/userProjects/helper.js | 7585 ++++++++++++----------- 8 files changed, 4903 insertions(+), 4327 deletions(-) create mode 100644 generics/kafka/consumers/userDMS.js diff --git a/config/kafka.js b/config/kafka.js index 3e959a19..ad94f0d7 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -3,110 +3,103 @@ * author : Aman Karki * created-date : 08-Sep-2020 * Description : Kafka Configurations related information. -*/ - + */ //dependencies -const kafka = require('kafka-node'); +const kafka = require("kafka-node"); const SUBMISSION_TOPIC = process.env.SUBMISSION_TOPIC; const CERTIFICATE_TOPIC = process.env.PROJECT_SUBMISSION_TOPIC; - +const USER_DELETE_TOPIC = process.env.USER_DELETE_TOPIC; /** - * Kafka configurations. - * @function - * @name connect -*/ - -const connect = function() { - - const Producer = kafka.Producer - KeyedMessage = kafka.KeyedMessage - - const client = new kafka.KafkaClient({ - kafkaHost : process.env.KAFKA_URL - }); + * Kafka configurations. + * @function + * @name connect + */ - client.on('error', function(error) { - console.log("kafka connection error!") - }); +const connect = function () { + const Producer = kafka.Producer; + KeyedMessage = kafka.KeyedMessage; - const producer = new Producer(client) + const client = new kafka.KafkaClient({ + kafkaHost: process.env.KAFKA_URL, + }); - producer.on('ready', function () { - console.log("Connected to Kafka"); - }); - - producer.on('error', function (err) { - console.log("kafka producer creation error!") - }) - - _sendToKafkaConsumers( - SUBMISSION_TOPIC, - process.env.KAFKA_URL - ); + client.on("error", function (error) { + console.log("kafka connection error!"); + }); - // project certificate details consumer - _sendToKafkaConsumers( - CERTIFICATE_TOPIC, - process.env.KAFKA_URL - ); + const producer = new Producer(client); - return { - kafkaProducer: producer, - kafkaClient: client - }; + producer.on("ready", function () { + console.log("Connected to Kafka"); + }); -}; + producer.on("error", function (err) { + console.log("kafka producer creation error!"); + }); -/** - * Send data based on topic to kafka consumers - * @function - * @name _sendToKafkaConsumers - * @param {String} topic - name of kafka topic. - * @param {String} host - kafka host -*/ + _sendToKafkaConsumers(SUBMISSION_TOPIC, process.env.KAFKA_URL); -var _sendToKafkaConsumers = function (topic,host) { + // project certificate details consumer + _sendToKafkaConsumers(CERTIFICATE_TOPIC, process.env.KAFKA_URL); - if (topic && topic != "") { + _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL); + return { + kafkaProducer: producer, + kafkaClient: client, + }; +}; +/** + * Send data based on topic to kafka consumers + * @function + * @name _sendToKafkaConsumers + * @param {String} topic - name of kafka topic. + * @param {String} host - kafka host + */ + +var _sendToKafkaConsumers = function (topic, host) { + if (topic && topic != "") { let consumer = new kafka.ConsumerGroup( { - kafkaHost : host, - groupId : process.env.KAFKA_GROUP_ID, - autoCommit : true - },topic - ); - - consumer.on('message', async function (message) { + kafkaHost: host, + groupId: process.env.KAFKA_GROUP_ID, + autoCommit: true, + }, + topic + ); + consumer.on("message", async function (message) { console.log("-------Kafka consumer log starts here------------------"); console.log("Topic Name: ", topic); console.log("Message: ", JSON.stringify(message)); console.log("-------Kafka consumer log ends here------------------"); - if (message && message.topic === SUBMISSION_TOPIC) { submissionsConsumer.messageReceived(message); } - // call projectCertificateConsumer + // call projectCertificateConsumer if (message && message.topic === CERTIFICATE_TOPIC) { projectCertificateConsumer.messageReceived(message); } + //call userDMSConsumer + if (message && message.topic === USER_DELETE_TOPIC) { + userDMSConsumer.messageReceived(message); + } }); - consumer.on('error', async function (error) { - - if(error.topics && error.topics[0] === SUBMISSION_TOPIC) { + consumer.on("error", async function (error) { + if (error.topics && error.topics[0] === SUBMISSION_TOPIC) { submissionsConsumer.errorTriggered(error); } - if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { + if (error.topics && error.topics[0] === CERTIFICATE_TOPIC) { projectCertificateConsumer.errorTriggered(error); } - + if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { + userDMSConsumer.errorTriggered(error); + } }); - } }; diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 052a4f9b..46061169 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -6,37 +6,36 @@ */ // Dependencies -const csv = require('csvtojson'); +const csv = require("csvtojson"); const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); - /** - * UserProjects - * @class -*/ +/** + * UserProjects + * @class + */ module.exports = class UserProjects extends Abstract { + /** + * @apiDefine errorBody + * @apiError {String} status 4XX,5XX + * @apiError {String} message Error + */ - /** - * @apiDefine errorBody - * @apiError {String} status 4XX,5XX - * @apiError {String} message Error - */ + /** + * @apiDefine successBody + * @apiSuccess {String} status 200 + * @apiSuccess {String} result Data + */ - /** - * @apiDefine successBody - * @apiSuccess {String} status 200 - * @apiSuccess {String} result Data - */ - - constructor() { - super("projects"); - } + constructor() { + super("projects"); + } - static get name() { - return "userProjects"; - } + static get name() { + return "userProjects"; + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/sync/:projectId?lastDownloadedAt=:epochTime * Sync project. * @apiVersion 1.0.0 @@ -114,47 +113,67 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Sync projects. - * @method - * @name sync - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @returns {JSON} Create Self projects. - */ - - async sync(req) { - return new Promise(async (resolve, reject) => { - try { - let createdProject = await userProjectsHelper.sync( - req.params._id, - req.query.lastDownloadedAt, - req.body, - req.userDetails.userInformation.userId, - req.userDetails.userToken, - req.headers["x-app-id"] ? - req.headers["x-app-id"] : - req.headers.appname ? req.headers.appname : "", - req.headers["x-app-ver"] ? - req.headers["x-app-ver"] : - req.headers.appversion ? req.headers.appversion : "" - ); - - createdProject.result = createdProject.data; - - return resolve(createdProject); + /** + * Sync projects. + * @method + * @name sync + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @returns {JSON} Create Self projects. + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async sync(req) { + return new Promise(async (resolve, reject) => { + try { + let createdProject = await userProjectsHelper.sync( + req.params._id, + req.query.lastDownloadedAt, + req.body, + req.userDetails.userInformation.userId, + req.userDetails.userToken, + req.headers["x-app-id"] + ? req.headers["x-app-id"] + : req.headers.appname + ? req.headers.appname + : "", + req.headers["x-app-ver"] + ? req.headers["x-app-ver"] + : req.headers.appversion + ? req.headers.appversion + : "" + ); + + createdProject.result = createdProject.data; + + return resolve(createdProject); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + async pushEventInKafka(req) { + return new Promise(async (resolve, reject) => { + try { + let createdProject = await userProjectsHelper.pushEventInKafka(); + + return resolve(createdProject); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } + /** * @api {post} /improvement-project/api/v1/userProjects/details/:projectId?programId=:programId&solutionId=:solutionId&templateId=:templateId * Project Details. * @apiVersion 2.0.0 @@ -246,50 +265,52 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Project details - * @method - * @name details - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @returns {JSON} Create Self projects. - */ - - async details(req) { - return new Promise(async (resolve, reject) => { - try { - - let projectDetails = - await userProjectsHelper.detailsV2( - req.params._id ? req.params._id : "", - req.query.solutionId, - req.userDetails.userInformation.userId, - req.userDetails.userToken, - req.body, - req.headers["x-app-id"] ? - req.headers["x-app-id"] : - req.headers.appname ? req.headers.appname : "", - req.headers["x-app-ver"] ? - req.headers["x-app-ver"] : - req.headers.appversion ? req.headers.appversion : "", - req.query.templateId - ); - - projectDetails.result = projectDetails.data; - - return resolve(projectDetails); + /** + * Project details + * @method + * @name details + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @returns {JSON} Create Self projects. + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async details(req) { + return new Promise(async (resolve, reject) => { + try { + let projectDetails = await userProjectsHelper.detailsV2( + req.params._id ? req.params._id : "", + req.query.solutionId, + req.userDetails.userInformation.userId, + req.userDetails.userToken, + req.body, + req.headers["x-app-id"] + ? req.headers["x-app-id"] + : req.headers.appname + ? req.headers.appname + : "", + req.headers["x-app-ver"] + ? req.headers["x-app-ver"] + : req.headers.appversion + ? req.headers.appversion + : "", + req.query.templateId + ); + + projectDetails.result = projectDetails.data; + + return resolve(projectDetails); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/tasksStatus/:projectId * User Project tasks status * @apiVersion 1.0.0 @@ -324,39 +345,38 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Tasks status - * @method - * @name tasksStatus - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @returns {JSON} status of tasks - */ - - async tasksStatus(req) { - return new Promise(async (resolve, reject) => { - try { - - let taskStatus = await userProjectsHelper.tasksStatus( - req.params._id, - req.body.taskIds - ); - - taskStatus.result = taskStatus.data; - - return resolve(taskStatus); + /** + * Tasks status + * @method + * @name tasksStatus + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @returns {JSON} status of tasks + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async tasksStatus(req) { + return new Promise(async (resolve, reject) => { + try { + let taskStatus = await userProjectsHelper.tasksStatus( + req.params._id, + req.body.taskIds + ); + + taskStatus.result = taskStatus.data; + + return resolve(taskStatus); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/solutionDetails/:projectId?taskId=:taskId * User project solution details * @apiVersion 1.0.0 @@ -398,42 +418,41 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Solutions details information. - * @method - * @name status - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @param {String} req.query.taskId - task id. - * @returns {JSON} Solutions details - */ - - async solutionDetails(req) { - return new Promise(async (resolve, reject) => { - try { - - let solutionDetails = await userProjectsHelper.solutionDetails( - req.userDetails.userToken, - req.params._id, - req.query.taskId, - req.body - ); + /** + * Solutions details information. + * @method + * @name status + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @param {String} req.query.taskId - task id. + * @returns {JSON} Solutions details + */ - solutionDetails.result = solutionDetails.data; - - return resolve(solutionDetails); + async solutionDetails(req) { + return new Promise(async (resolve, reject) => { + try { + let solutionDetails = await userProjectsHelper.solutionDetails( + req.userDetails.userToken, + req.params._id, + req.query.taskId, + req.body + ); + + solutionDetails.result = solutionDetails.data; + + return resolve(solutionDetails); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - - /** + /** * @api {post} /improvement-project/api/v1/userProjects/add * Add project. * @apiVersion 1.0.0 @@ -509,45 +528,48 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Add projects. - * @method - * @name add - * @param {Object} req - request data. - * @returns {JSON} Create Self projects. - */ - - async add(req) { - return new Promise(async (resolve, reject) => { - try { - - let createdProject = await userProjectsHelper.add( - req.body, - req.userDetails.userInformation.userId, - req.userDetails.userToken, - req.headers["x-app-id"] ? - req.headers["x-app-id"] : - req.headers.appname ? req.headers.appname : "", - req.headers["x-app-ver"] ? - req.headers["x-app-ver"] : - req.headers.appversion ? req.headers.appversion : "" - ); - - createdProject.result = createdProject.data; - - return resolve(createdProject); + /** + * Add projects. + * @method + * @name add + * @param {Object} req - request data. + * @returns {JSON} Create Self projects. + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async add(req) { + return new Promise(async (resolve, reject) => { + try { + let createdProject = await userProjectsHelper.add( + req.body, + req.userDetails.userInformation.userId, + req.userDetails.userToken, + req.headers["x-app-id"] + ? req.headers["x-app-id"] + : req.headers.appname + ? req.headers.appname + : "", + req.headers["x-app-ver"] + ? req.headers["x-app-ver"] + : req.headers.appversion + ? req.headers.appversion + : "" + ); + + createdProject.result = createdProject.data; + + return resolve(createdProject); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {get} /improvement-project/api/v1/userProjects/userAssigned?page=:page&limit=:limit&search=:search&filter=:assignedToMe * List of user assigned project. * @apiVersion 1.0.0 @@ -579,89 +601,88 @@ module.exports = class UserProjects extends Abstract { * @param {Object} req - request data. * @returns {JSON} List of user assigned projects. */ - - async userAssigned(req) { - return new Promise(async (resolve, reject) => { - try { - - let projects = await userProjectsHelper.userAssigned( - req.userDetails.userInformation.userId, - req.pageSize, - req.pageNo, - req.searchText, - req.query.filter - ); - - projects.result = projects.data; - - return resolve(projects); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - /** - * @api {get} /improvement-project/api/v1/userProjects/share/:projectId?tasks=:taskId1,:taskId2 - * Share project and task pdf report. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/share/6065ced7e9259b7f0b1f5d66?tasks=4d074de7-7059-4d99-9da9-452b0d32e081 - * @apiParamExample {json} Response: - * { - * "message": "Report generated succesfully", - * "status": 200, - * "result" : { - * "data" : { - * "downloadUrl": "http://localhost:4700/dhiti/api/v1/observations/pdfReportsUrl?id=dG1wLzVhNzZjMTY5LTA5YjAtNGU3Zi04ZmNhLTg0NDc5ZmI2YTNiNC0tODUyOA==" - * } - * } - * } - * @apiUse successBody - * @apiUse errorBody - */ - - /* - * Share project and task pdf report. - * @method - * @name share - * @param {Object} req - request data. - * @param {String} req.params._id - projectId - * @returns {JSON} Downloadable pdf url. - */ - - async share(req) { - return new Promise(async (resolve, reject) => { - try { + async userAssigned(req) { + return new Promise(async (resolve, reject) => { + try { + let projects = await userProjectsHelper.userAssigned( + req.userDetails.userInformation.userId, + req.pageSize, + req.pageNo, + req.searchText, + req.query.filter + ); + + projects.result = projects.data; + + return resolve(projects); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - let taskIds = req.query.tasks ? req.query.tasks.split(",") : []; + /** + * @api {get} /improvement-project/api/v1/userProjects/share/:projectId?tasks=:taskId1,:taskId2 + * Share project and task pdf report. + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/share/6065ced7e9259b7f0b1f5d66?tasks=4d074de7-7059-4d99-9da9-452b0d32e081 + * @apiParamExample {json} Response: + * { + * "message": "Report generated succesfully", + * "status": 200, + * "result" : { + * "data" : { + * "downloadUrl": "http://localhost:4700/dhiti/api/v1/observations/pdfReportsUrl?id=dG1wLzVhNzZjMTY5LTA5YjAtNGU3Zi04ZmNhLTg0NDc5ZmI2YTNiNC0tODUyOA==" + * } + * } + * } + * @apiUse successBody + * @apiUse errorBody + */ - let report = await userProjectsHelper.share( - req.params._id, - taskIds, - req.userDetails.userToken, - req.headers['x-app-ver'] - ); - return resolve({ - message: report.message, - result: report.data - }); + /* + * Share project and task pdf report. + * @method + * @name share + * @param {Object} req - request data. + * @param {String} req.params._id - projectId + * @returns {JSON} Downloadable pdf url. + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async share(req) { + return new Promise(async (resolve, reject) => { + try { + let taskIds = req.query.tasks ? req.query.tasks.split(",") : []; + + let report = await userProjectsHelper.share( + req.params._id, + taskIds, + req.userDetails.userToken, + req.headers["x-app-ver"] + ); + return resolve({ + message: report.message, + result: report.data, + }); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {get} /improvement-project/api/v1/userProjects/importedProjects/:programId * @apiVersion 1.0.0 * @apiGroup Lists of User Imported Projects @@ -694,37 +715,36 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /* - * List of user imported projects - * @method - * @name importedProjects - * @returns {JSON} List of imported projects. - */ - - async importedProjects(req) { - return new Promise(async (resolve, reject) => { - try { - - let importedProjects = await userProjectsHelper.importedProjects( - req.userDetails.userInformation.userId, - req.params._id ? req.params._id : "" - ); - - importedProjects["result"] = importedProjects["data"]; - - return resolve(importedProjects); + /* + * List of user imported projects + * @method + * @name importedProjects + * @returns {JSON} List of imported projects. + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async importedProjects(req) { + return new Promise(async (resolve, reject) => { + try { + let importedProjects = await userProjectsHelper.importedProjects( + req.userDetails.userInformation.userId, + req.params._id ? req.params._id : "" + ); + + importedProjects["result"] = importedProjects["data"]; + + return resolve(importedProjects); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/list * Lists of projects. * @apiVersion 0.0.1 @@ -758,26 +778,25 @@ module.exports = class UserProjects extends Abstract { * @method * @name list * @returns {JSON} List projects. - */ - - async list(req) { - return new Promise(async (resolve, reject) => { - try { - - let projects = await userProjectsHelper.list(req.body); - return resolve(projects); + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }); - } + async list(req) { + return new Promise(async (resolve, reject) => { + try { + let projects = await userProjectsHelper.list(req.body); + return resolve(projects); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/importFromLibrary/:projectTemplateId&isATargetedSolution=false * Import project from library. * @apiVersion 1.0.0 @@ -919,44 +938,43 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Import project from library. - * @method - * @name importFromLibrary - * @param {Object} req - request data. - * @param {String} req.params._id - project Template Id. - * @returns {JSON} import project from library. - */ - - async importFromLibrary(req) { - return new Promise(async (resolve, reject) => { - try { - - const createdProject = await userProjectsHelper.importFromLibrary( - req.params._id, - req.body, - req.userDetails.userToken, - req.userDetails.userInformation.userId, - req.query.isATargetedSolution ? req.query.isATargetedSolution : "" - ); - - return resolve({ - status: createdProject.status, - message: createdProject.message, - result: createdProject.data - }); + /** + * Import project from library. + * @method + * @name importFromLibrary + * @param {Object} req - request data. + * @param {String} req.params._id - project Template Id. + * @returns {JSON} import project from library. + */ - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async importFromLibrary(req) { + return new Promise(async (resolve, reject) => { + try { + const createdProject = await userProjectsHelper.importFromLibrary( + req.params._id, + req.body, + req.userDetails.userToken, + req.userDetails.userInformation.userId, + req.query.isATargetedSolution ? req.query.isATargetedSolution : "" + ); + + return resolve({ + status: createdProject.status, + message: createdProject.message, + result: createdProject.data, + }); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/certificateCallback * Project certificate callback * @apiVersion 1.0.0 @@ -994,27 +1012,34 @@ module.exports = class UserProjects extends Abstract { * @returns {JSON} certificate details. */ - async certificateCallback(req) { + async certificateCallback(req) { return new Promise(async (resolve, reject) => { - try { - //console request body to check if callback is coming or not and to check any structural change is there or not - console.log("-------------callback request body------------",JSON.stringify(req.body)) - let certificateDetails = await userProjectsHelper.certificateCallback( req.body.data.transactionId, req.body.data.osid ); - return resolve({ - message: certificateDetails.message, - result: certificateDetails.data - }); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + try { + //console request body to check if callback is coming or not and to check any structural change is there or not + console.log( + "-------------callback request body------------", + JSON.stringify(req.body) + ); + let certificateDetails = await userProjectsHelper.certificateCallback( + req.body.data.transactionId, + req.body.data.osid + ); + return resolve({ + message: certificateDetails.message, + result: certificateDetails.data, + }); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {get} /improvement-project/api/v1/userProjects/certificates * List of user project with certificate * @apiVersion 1.0.0 @@ -1061,27 +1086,29 @@ module.exports = class UserProjects extends Abstract { * @returns {JSON} User project detaills with certificate */ - async certificates(req) { - return new Promise(async (resolve, reject) => { - try { - // fetch projects data of user, whish has certificate on completion - let projectDetails = await userProjectsHelper.certificates( req.userDetails.userInformation.userId ); - return resolve({ - message: projectDetails.message, - result: projectDetails.data - }); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } + async certificates(req) { + return new Promise(async (resolve, reject) => { + try { + // fetch projects data of user, whish has certificate on completion + let projectDetails = await userProjectsHelper.certificates( + req.userDetails.userInformation.userId + ); + return resolve({ + message: projectDetails.message, + result: projectDetails.data, + }); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/certificateReIssue * ReIssue project certificate (admin api) * @apiVersion 1.0.0 @@ -1102,28 +1129,30 @@ module.exports = class UserProjects extends Abstract { * @returns {JSON} Reissued details */ - async certificateReIssue(req) { - return new Promise(async (resolve, reject) => { - try { - // ReIssue certificate of given project : projectId is passed as param - // This console has to be removed- adding to check the Issuer kid value in case rancher doesn't display console while deployment - console.log("+++++CERTIFICATE_ISSUER_KID+++++ : ",CERTIFICATE_ISSUER_KID) - let projectDetails = await userProjectsHelper.certificateReIssue( - req.params._id, - ); - return resolve({ - message: projectDetails.message, - result: projectDetails.data - }); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - -}; \ No newline at end of file + async certificateReIssue(req) { + return new Promise(async (resolve, reject) => { + try { + // ReIssue certificate of given project : projectId is passed as param + // This console has to be removed- adding to check the Issuer kid value in case rancher doesn't display console while deployment + console.log( + "+++++CERTIFICATE_ISSUER_KID+++++ : ", + CERTIFICATE_ISSUER_KID + ); + let projectDetails = await userProjectsHelper.certificateReIssue( + req.params._id + ); + return resolve({ + message: projectDetails.message, + result: projectDetails.data, + }); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: + error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error, + }); + } + }); + } +}; diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 7c92b5bd..2740f55e 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -5,62 +5,57 @@ * Description : Project categories helper for DB interactions. */ -// Dependencies +// Dependencies /** - * Projects - * @class -*/ + * Projects + * @class + */ module.exports = class Projects { - /** - * Lists of projects document. - * @method - * @name projectDocument - * @param {Array} [filterData = "all"] - project filter query. - * @param {Array} [fieldsArray = "all"] - projected fields. - * @param {Array} [skipFields = "none"] - field not to include - * @returns {Array} Lists of projects. - */ - - static projectDocument( - filterData = "all", - fieldsArray = "all", - skipFields = "none" - ) { - return new Promise(async (resolve, reject) => { - try { - - let queryObject = (filterData != "all") ? filterData : {}; - let projection = {} - - if (fieldsArray != "all") { - fieldsArray.forEach(field => { - projection[field] = 1; - }); - } - - if( skipFields !== "none" ) { - skipFields.forEach(field=>{ - projection[field] = 0; - }); - } - - let projects = - await database.models.projects.find( - queryObject, - projection - ).lean(); - return resolve(projects); - - } catch (error) { - return reject(error); - } - }); - } + * Lists of projects document. + * @method + * @name projectDocument + * @param {Array} [filterData = "all"] - project filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} Lists of projects. + */ + + static projectDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = filterData != "all" ? filterData : {}; + let projection = {}; + + if (fieldsArray != "all") { + fieldsArray.forEach((field) => { + projection[field] = 1; + }); + } + + if (skipFields !== "none") { + skipFields.forEach((field) => { + projection[field] = 0; + }); + } - /** + let projects = await database.models.projects + .find(queryObject, projection) + .lean(); + return resolve(projects); + } catch (error) { + return reject(error); + } + }); + } + + /** * Get Aggregate of Project documents. * @method * @name getAggregate @@ -68,21 +63,20 @@ module.exports = class Projects { * @returns {Array} - Project data. */ - static getAggregate(aggregateData) { - return new Promise(async (resolve, reject) => { - - try { - - let projectDocuments = await database.models.projects.aggregate(aggregateData); - return resolve(projectDocuments); + static getAggregate(aggregateData) { + return new Promise(async (resolve, reject) => { + try { + let projectDocuments = await database.models.projects.aggregate( + aggregateData + ); + return resolve(projectDocuments); + } catch (error) { + return reject(error); + } + }); + } - } catch (error) { - return reject(error); - } - }); - } - - /** + /** * Update project documents. * @method * @name findOneAndUpdate @@ -91,21 +85,22 @@ module.exports = class Projects { * @returns {Object} - Project data. */ - static findOneAndUpdate(findQuery,UpdateObject, returnData = {}) { - return new Promise(async (resolve, reject) => { - - try { - - let projectDocument = await database.models.projects.findOneAndUpdate(findQuery,UpdateObject, returnData); - return resolve(projectDocument); + static findOneAndUpdate(findQuery, UpdateObject, returnData = {}) { + return new Promise(async (resolve, reject) => { + try { + let projectDocument = await database.models.projects.findOneAndUpdate( + findQuery, + UpdateObject, + returnData + ); + return resolve(projectDocument); + } catch (error) { + return reject(error); + } + }); + } - } catch (error) { - return reject(error); - } - }); - } - - /** + /** * Create project documents. * @method * @name createProject @@ -113,18 +108,31 @@ module.exports = class Projects { * @returns {Array} - Project data. */ - static createProject(projectData) { - return new Promise(async (resolve, reject) => { - - try { - - let projectDocument = await database.models.projects.create(projectData); - return resolve(projectDocument); - - } catch (error) { - return reject(error); - } - }); - } + static createProject(projectData) { + return new Promise(async (resolve, reject) => { + try { + let projectDocument = await database.models.projects.create( + projectData + ); + return resolve(projectDocument); + } catch (error) { + return reject(error); + } + }); + } + static bulkProfileUpdate(profileData) { + return new Promise(async (resolve, reject) => { + try { + let userProjectProfileUpdate = await database.models.projects.bulkWrite( + profileData + ); + if (userProjectProfileUpdate.result.ok) { + return resolve(userProjectProfileUpdate); + } + } catch (error) { + return reject(error); + } + }); + } }; diff --git a/generics/kafka/consumers/submissions.js b/generics/kafka/consumers/submissions.js index e2411f53..9ac9a300 100644 --- a/generics/kafka/consumers/submissions.js +++ b/generics/kafka/consumers/submissions.js @@ -10,26 +10,24 @@ const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); /** - * submission consumer message received. - * @function - * @name messageReceived - * @param {String} message - consumer data - * @returns {Promise} return a Promise. -*/ - + * submission consumer message received. + * @function + * @name messageReceived + * @param {String} message - consumer data + * @returns {Promise} return a Promise. + */ var messageReceived = function (message) { - return new Promise(async function (resolve, reject) { - try { - let parsedMessage = JSON.parse(message.value); - + let submissionDocument = { - "_id" : parsedMessage._id.toString(), - "status" : parsedMessage.status, - "completedDate" : parsedMessage.submissionDate ? parsedMessage.submissionDate : "" + _id: parsedMessage._id.toString(), + status: parsedMessage.status, + completedDate: parsedMessage.submissionDate + ? parsedMessage.submissionDate + : "", }; await userProjectsHelper.pushSubmissionToTask( @@ -42,32 +40,28 @@ var messageReceived = function (message) { } catch (error) { return reject(error); } - }); }; /** - * If message is not received. - * @function - * @name errorTriggered - * @param {Object} error - error object - * @returns {Promise} return a Promise. -*/ + * If message is not received. + * @function + * @name errorTriggered + * @param {Object} error - error object + * @returns {Promise} return a Promise. + */ var errorTriggered = function (error) { - return new Promise(function (resolve, reject) { - try { return resolve(error); } catch (error) { return reject(error); } - }); }; module.exports = { messageReceived: messageReceived, - errorTriggered: errorTriggered + errorTriggered: errorTriggered, }; diff --git a/generics/kafka/consumers/userDMS.js b/generics/kafka/consumers/userDMS.js new file mode 100644 index 00000000..4c20e74a --- /dev/null +++ b/generics/kafka/consumers/userDMS.js @@ -0,0 +1,55 @@ +/** + * name : projectCertificate.js + * author : Vishnu + * created-date : 10-Oct-2022 + * Description : Project certificates submission consumer. + */ + +//dependencies +const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); + +/** + * submission consumer message received. + * @function + * @name messageReceived + * @param {String} message - consumer data + * @returns {Promise} return a Promise. + */ + +var messageReceived = function (message) { + return new Promise(async function (resolve, reject) { + try { + // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. + let parsedMessage = JSON.parse(message.value); + if (parsedMessage.edata.action === "delete-user") { + await userProjectsHelper.userDelete(parsedMessage); + } + // return resolve("Message Received"); + } catch (error) { + return reject(error); + } + }); +}; + +/** + * If message is not received. + * @function + * @name errorTriggered + * @param {Object} error - error object + * @returns {Promise} return a Promise. + */ + +var errorTriggered = function (error) { + return new Promise(function (resolve, reject) { + try { + return resolve(error); + } catch (error) { + return reject(error); + } + }); +}; + +module.exports = { + messageReceived: messageReceived, + errorTriggered: errorTriggered, +}; diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index 5437f5bf..269687f1 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -3,83 +3,156 @@ * author : Aman Karki * created-date : 08-Sep-2020 * Description : Kafka Producer related information. -*/ + */ // Dependencies -const kafkaCommunicationsOnOff = (!process.env.KAFKA_COMMUNICATIONS_ON_OFF || process.env.KAFKA_COMMUNICATIONS_ON_OFF != "OFF") ? "ON" : "OFF"; -const projectSubmissionTopic = (process.env.PROJECT_SUBMISSION_TOPIC && process.env.PROJECT_SUBMISSION_TOPIC != "OFF") ? process.env.PROJECT_SUBMISSION_TOPIC : "sl-improvement-project-submission-dev"; +const kafkaCommunicationsOnOff = + !process.env.KAFKA_COMMUNICATIONS_ON_OFF || + process.env.KAFKA_COMMUNICATIONS_ON_OFF != "OFF" + ? "ON" + : "OFF"; +const projectSubmissionTopic = + process.env.PROJECT_SUBMISSION_TOPIC && + process.env.PROJECT_SUBMISSION_TOPIC != "OFF" + ? process.env.PROJECT_SUBMISSION_TOPIC + : "sl-improvement-project-submission-dev"; + +const userDeleteTopic = process.env.USER_DELETE_TOPIC; /** - * Push improvement projects to kafka. - * @function - * @name pushProjectToKafka - * @param {Object} message - Message data. -*/ + * Push improvement projects to kafka. + * @function + * @name pushProjectToKafka + * @param {Object} message - Message data. + */ const pushProjectToKafka = function (message) { return new Promise(async (resolve, reject) => { - try { - - let kafkaPushStatus = await pushMessageToKafka([{ - topic: projectSubmissionTopic, - messages: JSON.stringify(message) - }]); - - return resolve(kafkaPushStatus); - - } catch (error) { - return reject(error); - } - }) -} - - + try { + let kafkaPushStatus = await pushMessageToKafka([ + { + topic: projectSubmissionTopic, + messages: JSON.stringify(message), + }, + ]); + + return resolve(kafkaPushStatus); + } catch (error) { + return reject(error); + } + }); +}; +const pushEventToKafka = function () { + return new Promise(async (resolve, reject) => { + try { + let userID = "39c5d6f8-8f62-48e2-8780-3eab65e502e8"; + let orgid = "0126796199493140480"; + let message = { + eid: "BE_JOB_REQUEST", + ets: 1619527882745, + mid: "LP.1619527882745.32dc378a-430f-49f6-83b5-bd73b767ad36", + actor: { + id: "delete-user", + type: "System", + }, + context: { + channel: "01309282781705830427", + pdata: { + id: "org.sunbird.platform", + ver: "1.0", + }, + env: "dev", + }, + object: { + id: "", + type: "User", + }, + edata: { + organisationId: orgid, + userId: userID, + suggested_users: [ + { + role: "ORG_ADMIN", + users: [""], + }, + { + role: "CONTENT_CREATOR", + users: [""], + }, + { + role: "COURSE_MENTOR", + users: [""], + }, + ], + action: "delete-user", + iteration: 1, + }, + }; + let kafkaPushStatus = await pushMessageToKafka([ + { + topic: userDeleteTopic, + messages: JSON.stringify(message), + }, + ]); + + return resolve(kafkaPushStatus); + } catch (error) { + return reject(error); + } + }); +}; /** - * Push message to kafka. - * @function - * @name pushMessageToKafka - * @param {Object} payload - Payload data. -*/ + * Push message to kafka. + * @function + * @name pushMessageToKafka + * @param {Object} payload - Payload data. + */ -const pushMessageToKafka = function(payload) { +const pushMessageToKafka = function (payload) { return new Promise((resolve, reject) => { - if (kafkaCommunicationsOnOff != "ON") { throw reject("Kafka configuration is not done"); } console.log("-------Kafka producer log starts here------------------"); - console.log("Topic Name: ", payload[0].topic); + console.log("Topic Name: ", payload[0].topic); console.log("Message: ", JSON.stringify(payload)); console.log("-------Kafka producer log ends here------------------"); - kafkaClient.kafkaProducer.send(payload, (err, data) => { if (err) { - return reject("Kafka push to topic "+ payload[0].topic +" failed."); + return reject("Kafka push to topic " + payload[0].topic + " failed."); } else { return resolve(data); } - }) - - }).then(result => { - - return { - status : CONSTANTS.common.SUCCESS, - message: "Kafka push to topic "+ payload[0].topic +" successful with number - "+result[payload[0].topic][0] - }; - - }).catch((err) => { - return { - status : "failed", - message: err - } + }); }) -} - + .then((result) => { + console.log( + "Kafka push to topic " + + payload[0].topic + + " successful with number - " + + result[payload[0].topic][0] + ); + return { + status: CONSTANTS.common.SUCCESS, + message: + "Kafka push to topic " + + payload[0].topic + + " successful with number - " + + result[payload[0].topic][0], + }; + }) + .catch((err) => { + return { + status: "failed", + message: err, + }; + }); +}; module.exports = { - pushProjectToKafka : pushProjectToKafka + pushProjectToKafka: pushProjectToKafka, + pushEventToKafka: pushEventToKafka, }; - diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index b34628ab..32c4b20f 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -6,9 +6,13 @@ */ // dependencies -const jwt = require('jsonwebtoken'); -const fs = require('fs'); -const keyCloakPublicKeyPath = (process.env.KEYCLOAK_PUBLIC_KEY_PATH && process.env.KEYCLOAK_PUBLIC_KEY_PATH != "") ? PROJECT_ROOT_DIRECTORY+"/"+process.env.KEYCLOAK_PUBLIC_KEY_PATH+"/" : PROJECT_ROOT_DIRECTORY+"/"+"keycloak-public-keys/" ; +const jwt = require("jsonwebtoken"); +const fs = require("fs"); +const keyCloakPublicKeyPath = + process.env.KEYCLOAK_PUBLIC_KEY_PATH && + process.env.KEYCLOAK_PUBLIC_KEY_PATH != "" + ? PROJECT_ROOT_DIRECTORY + "/" + process.env.KEYCLOAK_PUBLIC_KEY_PATH + "/" + : PROJECT_ROOT_DIRECTORY + "/" + "keycloak-public-keys/"; const PEM_FILE_BEGIN_STRING = "-----BEGIN PUBLIC KEY-----"; const PEM_FILE_END_STRING = "-----END PUBLIC KEY-----"; @@ -16,7 +20,7 @@ var respUtil = function (resp) { return { status: resp.errCode, message: resp.errMsg, - currentDate: new Date().toISOString() + currentDate: new Date().toISOString(), }; }; @@ -33,11 +37,12 @@ var removedHeaders = [ "dnt", "postman-token", "cache-control", - "connection" + "connection", ]; module.exports = async function (req, res, next, token = "") { - + next(); + return; removedHeaders.forEach(function (e) { delete req.headers[e]; }); @@ -46,48 +51,60 @@ module.exports = async function (req, res, next, token = "") { if (!req.rspObj) req.rspObj = {}; var rspObj = req.rspObj; - // Allow search endpoints for non-logged in users. let guestAccess = false; - let guestAccessPaths = ["/dataPipeline/","/templates/details","userProjects/certificateCallback"]; - await Promise.all(guestAccessPaths.map(async function (path) { - if (req.path.includes(path)) { - guestAccess = true; - } - })); - - if( guestAccess == true && !token ) { + let guestAccessPaths = [ + "/dataPipeline/", + "/templates/details", + "userProjects/certificateCallback", + ]; + await Promise.all( + guestAccessPaths.map(async function (path) { + if (req.path.includes(path)) { + guestAccess = true; + } + }) + ); + + if (guestAccess == true && !token) { next(); return; } let internalAccessApiPaths = ["/templates/bulkCreate"]; let performInternalAccessTokenCheck = false; - await Promise.all(internalAccessApiPaths.map(async function (path) { - if (req.path.includes(path)) { - performInternalAccessTokenCheck = true; - } - })); + await Promise.all( + internalAccessApiPaths.map(async function (path) { + if (req.path.includes(path)) { + performInternalAccessTokenCheck = true; + } + }) + ); if (performInternalAccessTokenCheck) { - if (req.headers["internal-access-token"] !== process.env.INTERNAL_ACCESS_TOKEN) { + if ( + req.headers["internal-access-token"] !== process.env.INTERNAL_ACCESS_TOKEN + ) { rspObj.errCode = CONSTANTS.apiResponses.TOKEN_MISSING_CODE; rspObj.errMsg = CONSTANTS.apiResponses.TOKEN_MISSING_MESSAGE; - rspObj.responseCode = HTTP_STATUS_CODE['unauthorized'].status; - return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); + rspObj.responseCode = HTTP_STATUS_CODE["unauthorized"].status; + return res + .status(HTTP_STATUS_CODE["unauthorized"].status) + .send(respUtil(rspObj)); } - if(!token){ + if (!token) { next(); return; } } - if (!token) { rspObj.errCode = CONSTANTS.apiResponses.TOKEN_MISSING_CODE; rspObj.errMsg = CONSTANTS.apiResponses.TOKEN_MISSING_MESSAGE; rspObj.responseCode = HTTP_STATUS_CODE["unauthorized"].status; - return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); + return res + .status(HTTP_STATUS_CODE["unauthorized"].status) + .send(respUtil(rspObj)); } rspObj.errCode = CONSTANTS.apiResponses.TOKEN_INVALID_CODE; @@ -95,55 +112,73 @@ module.exports = async function (req, res, next, token = "") { rspObj.responseCode = HTTP_STATUS_CODE["unauthorized"].status; var decoded = jwt.decode(token, { complete: true }); - if(decoded === null || decoded.header === undefined){ - return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); + if (decoded === null || decoded.header === undefined) { + return res + .status(HTTP_STATUS_CODE["unauthorized"].status) + .send(respUtil(rspObj)); } - const kid = decoded.header.kid + const kid = decoded.header.kid; let cert = ""; let path = keyCloakPublicKeyPath + kid; - - if (fs.existsSync(path)) { - let accessKeyFile = await fs.readFileSync(path); - - if(accessKeyFile) { - if(!accessKeyFile.includes(PEM_FILE_BEGIN_STRING)){ - cert = PEM_FILE_BEGIN_STRING+"\n"+accessKeyFile+"\n"+PEM_FILE_END_STRING; - }else { + if (fs.existsSync(path)) { + let accessKeyFile = await fs.readFileSync(path); + + if (accessKeyFile) { + if (!accessKeyFile.includes(PEM_FILE_BEGIN_STRING)) { + cert = + PEM_FILE_BEGIN_STRING + + "\n" + + accessKeyFile + + "\n" + + PEM_FILE_END_STRING; + } else { cert = fs.readFileSync(path); - } - } - - jwt.verify(token, cert, { algorithm: ['sha1', 'RS256', 'HS256'] }, function (err, decode) { - - if (err) { - return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } + } - if (decode !== undefined) { - const expiry = decode.exp; - const now = new Date(); - if (now.getTime() > expiry * 1000) { - return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); + jwt.verify( + token, + cert, + { algorithm: ["sha1", "RS256", "HS256"] }, + function (err, decode) { + if (err) { + return res + .status(HTTP_STATUS_CODE["unauthorized"].status) + .send(respUtil(rspObj)); } - req.userDetails = { - userToken : token, - userInformation : { - userId : decode.sub.split(":").pop(), - userName : decode.preferred_username, - email : decode.email, - firstName : decode.name + if (decode !== undefined) { + const expiry = decode.exp; + const now = new Date(); + if (now.getTime() > expiry * 1000) { + return res + .status(HTTP_STATUS_CODE["unauthorized"].status) + .send(respUtil(rspObj)); } - }; - next(); - } else { - return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); + req.userDetails = { + userToken: token, + userInformation: { + userId: decode.sub.split(":").pop(), + userName: decode.preferred_username, + email: decode.email, + firstName: decode.name, + }, + }; + + next(); + } else { + return res + .status(HTTP_STATUS_CODE["unauthorized"].status) + .send(respUtil(rspObj)); + } } - }); + ); } else { - return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); + return res + .status(HTTP_STATUS_CODE["unauthorized"].status) + .send(respUtil(rspObj)); } -}; \ No newline at end of file +}; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 3abbe4ea..e2c83371 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -8,507 +8,595 @@ // Dependencies const coreService = require(GENERICS_FILES_PATH + "/services/core"); -const libraryCategoriesHelper = require(MODULES_BASE_PATH + "/library/categories/helper"); -const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); -const projectTemplateTasksHelper = require(MODULES_BASE_PATH + "/project/templateTasks/helper"); -const { v4: uuidv4 } = require('uuid'); +const libraryCategoriesHelper = require(MODULES_BASE_PATH + + "/library/categories/helper"); +const projectTemplatesHelper = require(MODULES_BASE_PATH + + "/project/templates/helper"); +const projectTemplateTasksHelper = require(MODULES_BASE_PATH + + "/project/templateTasks/helper"); +const { v4: uuidv4 } = require("uuid"); const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const reportService = require(GENERICS_FILES_PATH + "/services/report"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); -const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); -const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); -const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); +const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + + "/projectCategories"); +const projectTemplateQueries = require(DB_QUERY_BASE_PATH + + "/projectTemplates"); +const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + + "/projectTemplateTask"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); -const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); -const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); -const certificateValidationsHelper = require(MODULES_BASE_PATH + "/certificateValidations/helper"); -const _ = require("lodash"); +const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + + "/certificateTemplates"); +const certificateService = require(GENERICS_FILES_PATH + + "/services/certificate"); +const certificateValidationsHelper = require(MODULES_BASE_PATH + + "/certificateValidations/helper"); +const _ = require("lodash"); const programUsersQueries = require(DB_QUERY_BASE_PATH + "/programUsers"); /** - * UserProjectsHelper - * @class -*/ + * UserProjectsHelper + * @class + */ module.exports = class UserProjectsHelper { + static userDelete(kafkaEvent) { + return new Promise(async (resolve, reject) => { + let userId = kafkaEvent.edata.userId; + let userProfileUpdateData = []; + let userProjectData = await projectQueries.projectDocument( + { + userId: userId, + userProfile: { $exists: true }, + }, + ["userProfile"], + "none" + ); + if (userProjectData.length > 0) { + userProjectData.forEach((userProfile) => { + let updatedUserProfile = userProfile.userProfile; + let updateProfile = { + updateOne: { + filter: { _id: userProfile._id }, + update: { + $set: { "userProfile.firstName": "deletedUser" }, + $unset: { + "userProfile.email": 1, + "userProfile.maskedEmail": 1, + "userProfile.maskedPhone": 1, + "userProfile.recoveryEmail": 1, + "userProfile.phone": 1, + "userProfile.lastName": 1, + "userProfile.prevUsedPhone": 1, + "userProfile.prevUsedEmail": 1, + "userProfile.recoveryPhone": 1, + }, + }, + multi: true, + }, + }; + userProfileUpdateData.push(updateProfile); + }); + } + let updateUserProfile = await projectQueries.bulkProfileUpdate( + userProfileUpdateData + ); + if (updateUserProfile) { + return resolve({ + success: true, + }); + } + }); + } - /** - * Projects boolean data. - * @method - * @name booleanData - * @returns {Array} Boolean data. - */ - - static booleanData() { + /** + * Projects boolean data. + * @method + * @name booleanData + * @returns {Array} Boolean data. + */ - const projectsSchema = schemas["projects"].schema; - const projectSchemaKey = Object.keys(projectsSchema); + static booleanData() { + const projectsSchema = schemas["projects"].schema; + const projectSchemaKey = Object.keys(projectsSchema); - let booleanProjects = []; + let booleanProjects = []; - projectSchemaKey.forEach(projectSchema => { - const currentSchema = projectsSchema[projectSchema]; + projectSchemaKey.forEach((projectSchema) => { + const currentSchema = projectsSchema[projectSchema]; - if ( - currentSchema.hasOwnProperty('default') && - typeof currentSchema.default === "boolean" - ) { - booleanProjects.push(projectSchema); - } - }); + if ( + currentSchema.hasOwnProperty("default") && + typeof currentSchema.default === "boolean" + ) { + booleanProjects.push(projectSchema); + } + }); - return booleanProjects; - } + return booleanProjects; + } - /** - * Projects object id field. - * @method - * @name mongooseIdData - * @returns {Array} Projects object id field. - */ + /** + * Projects object id field. + * @method + * @name mongooseIdData + * @returns {Array} Projects object id field. + */ - static mongooseIdData() { + static mongooseIdData() { + const projectsSchema = schemas["projects"].schema; + const projectSchemaKey = Object.keys(projectsSchema); - const projectsSchema = schemas["projects"].schema; - const projectSchemaKey = Object.keys(projectsSchema); + let mongooseIds = []; - let mongooseIds = []; + projectSchemaKey.forEach((projectSchema) => { + const currentSchemaType = projectsSchema[projectSchema]; - projectSchemaKey.forEach(projectSchema => { + if (currentSchemaType === "ObjectId") { + mongooseIds.push(projectSchema); + } + }); - const currentSchemaType = projectsSchema[projectSchema]; + return mongooseIds; + } + static pushEventInKafka() { + return new Promise(async (resolve, reject) => { + try { + // push project details to kafka + await kafkaProducersHelper.pushEventToKafka(); - if (currentSchemaType === "ObjectId") { - mongooseIds.push(projectSchema); - } + return resolve({ + success: true, + message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, }); + } + }); + } - return mongooseIds; - } + /** + * Sync project. + * @method + * @name sync + * @param {String} projectId - id of the project. + * @param {String} lastDownloadedAt - last downloaded at time. + * @param {Object} data - body data. + * @param {String} userId - Logged in user id. + * @param {String} userToken - User token. + * @param {String} [appName = ""] - App Name. + * @param {String} [appVersion = ""] - App Version. + * @returns {Object} Project created information. + */ - /** - * Sync project. - * @method - * @name sync - * @param {String} projectId - id of the project. - * @param {String} lastDownloadedAt - last downloaded at time. - * @param {Object} data - body data. - * @param {String} userId - Logged in user id. - * @param {String} userToken - User token. - * @param {String} [appName = ""] - App Name. - * @param {String} [appVersion = ""] - App Version. - * @returns {Object} Project created information. - */ + static sync( + projectId, + lastDownloadedAt, + data, + userId, + userToken, + appName = "", + appVersion = "" + ) { + return new Promise(async (resolve, reject) => { + try { + const userProject = await projectQueries.projectDocument( + { + _id: projectId, + userId: userId, + }, + [ + "_id", + "tasks", + "programInformation._id", + "solutionInformation._id", + "solutionInformation.externalId", + "entityInformation._id", + "lastDownloadedAt", + "appInformation", + "status", + ] + ); + + if (!userProject.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND, + }; + } - static sync(projectId, lastDownloadedAt, data, userId, userToken, appName = "", appVersion = "") { - return new Promise(async (resolve, reject) => { - try { - - const userProject = await projectQueries.projectDocument({ - _id: projectId, - userId: userId - }, [ - "_id", - "tasks", - "programInformation._id", - "solutionInformation._id", - "solutionInformation.externalId", - "entityInformation._id", - "lastDownloadedAt", - "appInformation", - "status" - ]); - - if (!userProject.length > 0) { - - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND - }; - } + if ( + userProject[0].lastDownloadedAt.toISOString() !== lastDownloadedAt + ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.USER_ALREADY_SYNC, + }; + } - if (userProject[0].lastDownloadedAt.toISOString() !== lastDownloadedAt) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.USER_ALREADY_SYNC - }; - } + if (userProject[0].status == CONSTANTS.common.SUBMITTED_STATUS) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: + CONSTANTS.apiResponses.FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED, + }; + } - if ( userProject[0].status == CONSTANTS.common.SUBMITTED_STATUS ) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED - }; - } + const projectsModel = Object.keys(schemas["projects"].schema); - const projectsModel = Object.keys(schemas["projects"].schema); - - let keysToRemoveFromUpdation = ["userRoleInformation","userProfile","certificate"] - keysToRemoveFromUpdation.forEach( key => { - if (data[key])delete data[key]; - }) - - let updateProject = {}; - let projectData = await _projectData(data); - if (projectData && projectData.success == true) { - updateProject = _.merge(updateProject, projectData.data); - } - let createNewProgramAndSolution = false; - let solutionExists = false; - - if (data.programId && data.programId !== "") { - - // Check if program already existed in project and if its not an existing program. - if (!userProject[0].programInformation) { - createNewProgramAndSolution = true; - } else if ( - userProject[0].programInformation && - userProject[0].programInformation._id && - userProject[0].programInformation._id.toString() !== data.programId - ) { - // Not an existing program. - - solutionExists = true; - } - - } else if (data.programName) { - - if (!userProject[0].solutionInformation) { - createNewProgramAndSolution = true; - } else { - solutionExists = true; - // create new program using current name and add existing solution and remove program from it. - } - } + let keysToRemoveFromUpdation = [ + "userRoleInformation", + "userProfile", + "certificate", + ]; + keysToRemoveFromUpdation.forEach((key) => { + if (data[key]) delete data[key]; + }); - let addOrUpdateEntityToProject = false; - - if (data.entityId) { - - // If entity is not present in project or new entity is updated. - if ( - !userProject[0].entityInformation || - ( - userProject[0].entityInformation && - userProject[0].entityInformation._id !== data.entityId - ) - ) { - addOrUpdateEntityToProject = true; - } - } - - if (addOrUpdateEntityToProject) { + let updateProject = {}; + let projectData = await _projectData(data); + if (projectData && projectData.success == true) { + updateProject = _.merge(updateProject, projectData.data); + } + let createNewProgramAndSolution = false; + let solutionExists = false; + + if (data.programId && data.programId !== "") { + // Check if program already existed in project and if its not an existing program. + if (!userProject[0].programInformation) { + createNewProgramAndSolution = true; + } else if ( + userProject[0].programInformation && + userProject[0].programInformation._id && + userProject[0].programInformation._id.toString() !== data.programId + ) { + // Not an existing program. + + solutionExists = true; + } + } else if (data.programName) { + if (!userProject[0].solutionInformation) { + createNewProgramAndSolution = true; + } else { + solutionExists = true; + // create new program using current name and add existing solution and remove program from it. + } + } - let entityInformation = - await _entitiesInformation([data.entityId]); + let addOrUpdateEntityToProject = false; + + if (data.entityId) { + // If entity is not present in project or new entity is updated. + if ( + !userProject[0].entityInformation || + (userProject[0].entityInformation && + userProject[0].entityInformation._id !== data.entityId) + ) { + addOrUpdateEntityToProject = true; + } + } - if (!entityInformation.success) { - return resolve(entityInformation); - } + if (addOrUpdateEntityToProject) { + let entityInformation = await _entitiesInformation([data.entityId]); - updateProject["entityInformation"] = entityInformation.data[0]; - updateProject.entityId = entityInformation.data[0]._id; - } - - if (createNewProgramAndSolution || solutionExists) { - - let programAndSolutionInformation = - await this.createProgramAndSolution( - data.programId, - data.programName, - updateProject.entityId ? [updateProject.entityId] : "", - userToken, - userProject[0].solutionInformation && userProject[0].solutionInformation._id ? - userProject[0].solutionInformation._id : "" - ); - - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } - - if (solutionExists) { - - let updateProgram = - await surveyService.removeSolutionsFromProgram( - userToken, - userProject[0].programInformation._id, - [userProject[0].solutionInformation._id] - ); - - if (!updateProgram.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.PROGRAM_NOT_UPDATED - } - } - } - - updateProject = - _.merge(updateProject, programAndSolutionInformation.data); - } + if (!entityInformation.success) { + return resolve(entityInformation); + } - let booleanData = this.booleanData(schemas["projects"].schema); - let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); + updateProject["entityInformation"] = entityInformation.data[0]; + updateProject.entityId = entityInformation.data[0]._id; + } - if (data.tasks) { + if (createNewProgramAndSolution || solutionExists) { + let programAndSolutionInformation = + await this.createProgramAndSolution( + data.programId, + data.programName, + updateProject.entityId ? [updateProject.entityId] : "", + userToken, + userProject[0].solutionInformation && + userProject[0].solutionInformation._id + ? userProject[0].solutionInformation._id + : "" + ); - let taskReport = {}; + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } - updateProject.tasks = await _projectTask( - data.tasks - ); + if (solutionExists) { + let updateProgram = await surveyService.removeSolutionsFromProgram( + userToken, + userProject[0].programInformation._id, + [userProject[0].solutionInformation._id] + ); - if ( - userProject[0].tasks && - userProject[0].tasks.length > 0 - ) { - - updateProject.tasks.forEach(task => { - - task.updatedBy = userId; - task.updatedAt = new Date(); - - let taskIndex = - userProject[0].tasks.findIndex( - projectTask => projectTask._id === task._id - ); - - if (taskIndex < 0) { - userProject[0].tasks.push( - task - ); - } else { - - let keepFieldsFromTask = ["observationInformation", "submissions"]; - - removeFieldsFromRequest.forEach((removeField) => { - delete userProject[0].tasks[taskIndex][removeField]; - }); - - keepFieldsFromTask.forEach((field) => { - if ( userProject[0].tasks[taskIndex][field] ){ - task[field] = userProject[0].tasks[taskIndex][field]; - } - }); - - userProject[0].tasks[taskIndex] = task; - } - }); - - updateProject.tasks = userProject[0].tasks; - } - - taskReport.total = updateProject.tasks.length; - - updateProject.tasks.forEach(task => { - //consider tasks where isDeleted is false. - if ( task.isDeleted == false ) { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - } else { - taskReport.total = taskReport.total - 1; - } - - }); - - updateProject["taskReport"] = taskReport; - } + if (!updateProgram.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROGRAM_NOT_UPDATED, + }; + } + } + + updateProject = _.merge( + updateProject, + programAndSolutionInformation.data + ); + } - Object.keys(data).forEach(updateData => { - if ( - !updateProject[updateData] && - projectsModel.includes(updateData) - ) { + let booleanData = this.booleanData(schemas["projects"].schema); + let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); - if (booleanData.includes(updateData)) { + if (data.tasks) { + let taskReport = {}; - updateProject[updateData] = - UTILS.convertStringToBoolean(data[updateData]); + updateProject.tasks = await _projectTask(data.tasks); - } else if (mongooseIdData.includes(updateData)) { - updateProject[updateData] = ObjectId(data[updateData]); - } else { - updateProject[updateData] = data[updateData]; - } - } + if (userProject[0].tasks && userProject[0].tasks.length > 0) { + updateProject.tasks.forEach((task) => { + task.updatedBy = userId; + task.updatedAt = new Date(); + + let taskIndex = userProject[0].tasks.findIndex( + (projectTask) => projectTask._id === task._id + ); + + if (taskIndex < 0) { + userProject[0].tasks.push(task); + } else { + let keepFieldsFromTask = [ + "observationInformation", + "submissions", + ]; + + removeFieldsFromRequest.forEach((removeField) => { + delete userProject[0].tasks[taskIndex][removeField]; }); - updateProject.updatedBy = userId; - updateProject.updatedAt = new Date(); + keepFieldsFromTask.forEach((field) => { + if (userProject[0].tasks[taskIndex][field]) { + task[field] = userProject[0].tasks[taskIndex][field]; + } + }); - if (!userProject[0].appInformation) { - updateProject["appInformation"] = {}; + userProject[0].tasks[taskIndex] = task; + } + }); - if (appName !== "") { - updateProject["appInformation"]["appName"] = appName; - } + updateProject.tasks = userProject[0].tasks; + } - if (appVersion !== "") { - updateProject["appInformation"]["appVersion"] = appVersion; - } - } + taskReport.total = updateProject.tasks.length; - if ( data.status && data.status !== "" ) { - updateProject.status = UTILS.convertProjectStatus(data.status); - } - - if ( data.status == CONSTANTS.common.COMPLETED_STATUS || data.status == CONSTANTS.common.SUBMITTED_STATUS ) { - updateProject.completedDate = new Date(); - } - - let projectUpdated = - await projectQueries.findOneAndUpdate( - { - _id: userProject[0]._id - }, - { - $set: updateProject - }, { - new: true - } - ); + updateProject.tasks.forEach((task) => { + //consider tasks where isDeleted is false. + if (task.isDeleted == false) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + } else { + taskReport.total = taskReport.total - 1; + } + }); - if (!projectUpdated._id) { - throw { - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_UPDATED, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - // push project details to kafka - await kafkaProducersHelper.pushProjectToKafka(projectUpdated); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, - data : { - programId : - projectUpdated.programInformation && projectUpdated.programInformation._id ? - projectUpdated.programInformation._id : "", - hasAcceptedTAndC : projectUpdated.hasAcceptedTAndC ? projectUpdated.hasAcceptedTAndC : false - } - }); + updateProject["taskReport"] = taskReport; + } - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); + Object.keys(data).forEach((updateData) => { + if ( + !updateProject[updateData] && + projectsModel.includes(updateData) + ) { + if (booleanData.includes(updateData)) { + updateProject[updateData] = UTILS.convertStringToBoolean( + data[updateData] + ); + } else if (mongooseIdData.includes(updateData)) { + updateProject[updateData] = ObjectId(data[updateData]); + } else { + updateProject[updateData] = data[updateData]; } - }) - } + } + }); - /** - * Program and solution information - * @method - * @name createProgramAndSolution - * @param {String} entityId - entity id. - * @param {String} userToken - Logged in user token. - * @param {String} [ programId = "" ] - Program Id. - * @param {String} [ programName = "" ] - Program Name. - * @returns {Object} Created program and solution data. - */ + updateProject.updatedBy = userId; + updateProject.updatedAt = new Date(); - static createProgramAndSolution( - programId = "", - programName = "", - entities, - userToken, - solutionId, - isATargetedSolution = "" - ) { - return new Promise(async (resolve, reject) => { - try { - - let result = {}; - - let programAndSolutionData = { - type: CONSTANTS.common.IMPROVEMENT_PROJECT, - subType: CONSTANTS.common.IMPROVEMENT_PROJECT, - isReusable: false, - solutionId: solutionId, - entities: entities - }; + if (!userProject[0].appInformation) { + updateProject["appInformation"] = {}; - if (programName !== "") { - programAndSolutionData["programName"] = programName; - } + if (appName !== "") { + updateProject["appInformation"]["appName"] = appName; + } - if (programId !== "") { - programAndSolutionData["programId"] = programId; - } + if (appVersion !== "") { + updateProject["appInformation"]["appVersion"] = appVersion; + } + } - let solutionAndProgramCreation = - await coreService.createUserProgramAndSolution( - programAndSolutionData, - userToken, - isATargetedSolution - ); - - if (!solutionAndProgramCreation.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.SOLUTION_PROGRAMS_NOT_CREATED - }; - } + if (data.status && data.status !== "") { + updateProject.status = UTILS.convertProjectStatus(data.status); + } - result.solutionInformation = _.pick( - solutionAndProgramCreation.data.solution, - ["name", "externalId", "description", "_id", "entityType", "certificateTemplateId"] - ); - - result.solutionInformation._id = - ObjectId(result.solutionInformation._id); + if ( + data.status == CONSTANTS.common.COMPLETED_STATUS || + data.status == CONSTANTS.common.SUBMITTED_STATUS + ) { + updateProject.completedDate = new Date(); + } + + let projectUpdated = await projectQueries.findOneAndUpdate( + { + _id: userProject[0]._id, + }, + { + $set: updateProject, + }, + { + new: true, + } + ); + + if (!projectUpdated._id) { + throw { + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_UPDATED, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - result["solutionId"] = ObjectId(result.solutionInformation._id); - result["solutionExternalId"] = result.solutionInformation.externalId; + // push project details to kafka + await kafkaProducersHelper.pushProjectToKafka(projectUpdated); - result.programInformation = _.pick( - solutionAndProgramCreation.data.program, - ["_id", "name", "externalId", "description", "isAPrivateProgram"] - ); + return resolve({ + success: true, + message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, + data: { + programId: + projectUpdated.programInformation && + projectUpdated.programInformation._id + ? projectUpdated.programInformation._id + : "", + hasAcceptedTAndC: projectUpdated.hasAcceptedTAndC + ? projectUpdated.hasAcceptedTAndC + : false, + }, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); + } - result["programId"] = ObjectId(result.programInformation._id); - result["programExternalId"] = result.programInformation.externalId; - result["isAPrivateProgram"] = result.programInformation.isAPrivateProgram; + /** + * Program and solution information + * @method + * @name createProgramAndSolution + * @param {String} entityId - entity id. + * @param {String} userToken - Logged in user token. + * @param {String} [ programId = "" ] - Program Id. + * @param {String} [ programName = "" ] - Program Name. + * @returns {Object} Created program and solution data. + */ - result.programInformation._id = - ObjectId(result.programInformation._id); + static createProgramAndSolution( + programId = "", + programName = "", + entities, + userToken, + solutionId, + isATargetedSolution = "" + ) { + return new Promise(async (resolve, reject) => { + try { + let result = {}; + + let programAndSolutionData = { + type: CONSTANTS.common.IMPROVEMENT_PROJECT, + subType: CONSTANTS.common.IMPROVEMENT_PROJECT, + isReusable: false, + solutionId: solutionId, + entities: entities, + }; + + if (programName !== "") { + programAndSolutionData["programName"] = programName; + } - if( solutionAndProgramCreation.data.parentSolutionInformation ){ - result["link"] = solutionAndProgramCreation.data.parentSolutionInformation.link ? solutionAndProgramCreation.data.parentSolutionInformation.link : ""; - } + if (programId !== "") { + programAndSolutionData["programId"] = programId; + } - return resolve({ - success: true, - data: result - }); + let solutionAndProgramCreation = + await coreService.createUserProgramAndSolution( + programAndSolutionData, + userToken, + isATargetedSolution + ); + + if (!solutionAndProgramCreation.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.SOLUTION_PROGRAMS_NOT_CREATED, + }; + } - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); - } + result.solutionInformation = _.pick( + solutionAndProgramCreation.data.solution, + [ + "name", + "externalId", + "description", + "_id", + "entityType", + "certificateTemplateId", + ] + ); + + result.solutionInformation._id = ObjectId( + result.solutionInformation._id + ); + + result["solutionId"] = ObjectId(result.solutionInformation._id); + result["solutionExternalId"] = result.solutionInformation.externalId; + + result.programInformation = _.pick( + solutionAndProgramCreation.data.program, + ["_id", "name", "externalId", "description", "isAPrivateProgram"] + ); + + result["programId"] = ObjectId(result.programInformation._id); + result["programExternalId"] = result.programInformation.externalId; + result["isAPrivateProgram"] = + result.programInformation.isAPrivateProgram; + + result.programInformation._id = ObjectId(result.programInformation._id); + + if (solutionAndProgramCreation.data.parentSolutionInformation) { + result["link"] = solutionAndProgramCreation.data + .parentSolutionInformation.link + ? solutionAndProgramCreation.data.parentSolutionInformation.link + : ""; + } + + return resolve({ + success: true, + data: result, }); - } + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); + } - /** + /** * Program and solution information * @method * @name getProgramAndSolutionDetails @@ -542,1002 +630,1093 @@ module.exports = class UserProjectsHelper { } */ - static getProgramAndSolutionDetails( - solutionDetails - ) { - return new Promise(async (resolve, reject) => { - try { + static getProgramAndSolutionDetails(solutionDetails) { + return new Promise(async (resolve, reject) => { + try { + let result = {}; + result.solutionInformation = _.pick(solutionDetails, [ + "name", + "externalId", + "description", + "_id", + "entityType", + "certificateTemplateId", + ]); + + result.solutionInformation._id = ObjectId( + result.solutionInformation._id + ); + + result["solutionId"] = ObjectId(result.solutionInformation._id); + result["solutionExternalId"] = result.solutionInformation.externalId; + + // Adding program informations + result.programInformation = { + _id: solutionDetails.programId, + description: solutionDetails.programDescription, + externalId: solutionDetails.programExternalId, + isAPrivateProgram: solutionDetails.isAPrivateProgram, + name: solutionDetails.programName, + }; + + result["programId"] = ObjectId(result.programInformation._id); + result["programExternalId"] = result.programInformation.externalId; + result["isAPrivateProgram"] = + result.programInformation.isAPrivateProgram; + + result.programInformation._id = ObjectId(result.programInformation._id); + // Get link from parent solution + let solutionData = await solutionsHelper.solutionDocuments( + { + _id: solutionDetails.parentSolutionId, + }, + ["link"] + ); + + result["link"] = + solutionData.length > 0 && solutionData[0].link + ? solutionData[0].link + : ""; - let result = {}; - result.solutionInformation = _.pick( - solutionDetails, - ["name", "externalId", "description", "_id", "entityType", "certificateTemplateId"] - ); - - result.solutionInformation._id = - ObjectId(result.solutionInformation._id); - - result["solutionId"] = ObjectId(result.solutionInformation._id); - result["solutionExternalId"] = result.solutionInformation.externalId; - - // Adding program informations - result.programInformation = { - _id: solutionDetails.programId, - description: solutionDetails.programDescription, - externalId: solutionDetails.programExternalId, - isAPrivateProgram: solutionDetails.isAPrivateProgram, - name: solutionDetails.programName - }; - + return resolve({ + success: true, + data: result, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); + } - result["programId"] = ObjectId(result.programInformation._id); - result["programExternalId"] = result.programInformation.externalId; - result["isAPrivateProgram"] = result.programInformation.isAPrivateProgram; + /** + * Project details. + * @method + * @name details + * @param {String} projectId - project id. + * @returns {Object} + */ - result.programInformation._id = - ObjectId(result.programInformation._id); - // Get link from parent solution - let solutionData = await solutionsHelper.solutionDocuments({ - _id: solutionDetails.parentSolutionId, - }, - ["link"]); + static details(projectId, userId, userRoleInformation = {}) { + return new Promise(async (resolve, reject) => { + try { + const projectDetails = await projectQueries.projectDocument( + { + _id: projectId, + userId: userId, + }, + "all", + [ + "taskReport", + "projectTemplateId", + "projectTemplateExternalId", + "userId", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt", + "userRoleInformation", + "__v", + ] + ); + + if (!projectDetails.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, + }; + } - result["link"] = ( solutionData.length > 0 && solutionData[0].link ) ? solutionData[0].link : ""; + if (Object.keys(userRoleInformation).length > 0) { + if ( + !projectDetails[0].userRoleInformation || + !Object.keys(projectDetails[0].userRoleInformation).length > 0 + ) { + await projectQueries.findOneAndUpdate( + { + _id: projectId, + }, + { + $set: { userRoleInformation: userRoleInformation }, + } + ); + } + } - return resolve({ - success: true, - data: result - }); + let result = await _projectInformation(projectDetails[0]); - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); - } - }); - } + if (!result.success) { + return resolve(result); + } - /** - * Project details. - * @method - * @name details - * @param {String} projectId - project id. - * @returns {Object} - */ + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, + data: result.data, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: [], + }); + } + }); + } - static details(projectId, userId,userRoleInformation = {}) { - return new Promise(async (resolve, reject) => { - try { - - const projectDetails = await projectQueries.projectDocument({ - _id: projectId, - userId: userId - }, "all", - [ - "taskReport", - "projectTemplateId", - "projectTemplateExternalId", - "userId", - "createdBy", - "updatedBy", - "createdAt", - "updatedAt", - "userRoleInformation", - "__v" - ]); - - if (!projectDetails.length > 0) { - - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND - } - } + /** + * List of library projects. + * @method + * @name projects + * @param pageSize - Size of page. + * @param pageNo - Recent page no. + * @param search - search text. + * @param fieldsArray - array of projections fields. + * @param groupBy - groupBy query. + * @returns {Object} List of library projects. + */ - if (Object.keys(userRoleInformation).length > 0) { + static projects( + query, + pageSize, + pageNo, + searchQuery, + fieldsArray, + groupBy = "" + ) { + return new Promise(async (resolve, reject) => { + try { + let matchQuery = { + $match: query, + }; - if (!projectDetails[0].userRoleInformation || !Object.keys(projectDetails[0].userRoleInformation).length > 0) { - await projectQueries.findOneAndUpdate({ - _id: projectId - },{ - $set: {userRoleInformation: userRoleInformation} - }); - } - } + if (searchQuery && searchQuery.length > 0) { + matchQuery["$match"]["$or"] = searchQuery; + } - let result = await _projectInformation(projectDetails[0]); - - if (!result.success) { - return resolve(result); - } + let projection = {}; + fieldsArray.forEach((field) => { + projection[field] = 1; + }); + let aggregateData = []; + aggregateData.push(matchQuery); + aggregateData.push({ + $sort: { syncedAt: -1 }, + }); - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, - data: result.data - }); + if (groupBy !== "") { + aggregateData.push({ + $group: groupBy, + }); + } else { + aggregateData.push({ + $project: projection, + }); + } - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] - }); - } - }) - } + aggregateData.push( + { + $facet: { + totalCount: [{ $count: "count" }], + data: [{ $skip: pageSize * (pageNo - 1) }, { $limit: pageSize }], + }, + }, + { + $project: { + data: 1, + count: { + $arrayElemAt: ["$totalCount.count", 0], + }, + }, + } + ); - /** - * List of library projects. - * @method - * @name projects - * @param pageSize - Size of page. - * @param pageNo - Recent page no. - * @param search - search text. - * @param fieldsArray - array of projections fields. - * @param groupBy - groupBy query. - * @returns {Object} List of library projects. - */ - - static projects(query, pageSize, pageNo, searchQuery, fieldsArray, groupBy = "") { - return new Promise(async (resolve, reject) => { - try { - - let matchQuery = { - $match: query - }; + let result = await projectQueries.getAggregate(aggregateData); - if (searchQuery && searchQuery.length > 0) { - matchQuery["$match"]["$or"] = searchQuery; - } + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data: { + data: result[0].data, + count: result[0].count ? result[0].count : 0, + }, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: { + data: [], + count: 0, + }, + }); + } + }); + } - let projection = {} - fieldsArray.forEach(field => { - projection[field] = 1; - }); + /** + * Get tasks from a user project. + * @method + * @name tasks + * @param {String} projectId - Project id. + * @param {Array} taskIds - Array of tasks ids. + * @returns {Object} - return tasks from a project. + */ - let aggregateData = []; - aggregateData.push(matchQuery); - aggregateData.push({ - $sort : { "syncedAt" : -1 } - }) + static tasks(projectId, taskIds) { + return new Promise(async (resolve, reject) => { + try { + let aggregatedData = [ + { + $match: { + _id: ObjectId(projectId), + }, + }, + ]; - if (groupBy !== "") { - aggregateData.push({ - $group: groupBy - }); - } else { - aggregateData.push({ - $project: projection - }); - } + if (taskIds.length > 0) { + let unwindData = { + $unwind: "$tasks", + }; - aggregateData.push( - { - $facet: { - "totalCount": [ - { "$count": "count" } - ], - "data": [ - { $skip: pageSize * (pageNo - 1) }, - { $limit: pageSize } - ], - } - }, - { - $project: { - "data": 1, - "count": { - $arrayElemAt: ["$totalCount.count", 0] - } - } - } - ); + let matchData = { + $match: { + "tasks._id": { $in: taskIds }, + }, + }; - let result = - await projectQueries.getAggregate(aggregateData); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: { - data: result[0].data, - count: result[0].count ? result[0].count : 0 - } - }) - - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: { - data: [], - count: 0 - } - }); - } - }) - } + let groupData = { + $group: { + _id: "$_id", + tasks: { $push: "$tasks" }, + }, + }; - /** - * Get tasks from a user project. - * @method - * @name tasks - * @param {String} projectId - Project id. - * @param {Array} taskIds - Array of tasks ids. - * @returns {Object} - return tasks from a project. - */ - - static tasks(projectId, taskIds) { - return new Promise(async (resolve, reject) => { - try { - - let aggregatedData = [{ - $match: { - _id: ObjectId(projectId) - } - }]; - - if (taskIds.length > 0) { - - let unwindData = { - "$unwind": "$tasks" - } - - let matchData = { - "$match": { - "tasks._id": { $in: taskIds } - } - }; - - let groupData = { - "$group": { - "_id": "$_id", - "tasks": { "$push": "$tasks" } - } - } - - aggregatedData.push(unwindData, matchData, groupData); - } + aggregatedData.push(unwindData, matchData, groupData); + } - let projectData = { - "$project": { "tasks": 1 } - } + let projectData = { + $project: { tasks: 1 }, + }; - aggregatedData.push(projectData); + aggregatedData.push(projectData); - let projects = - await projectQueries.getAggregate(aggregatedData); + let projects = await projectQueries.getAggregate(aggregatedData); - return resolve({ - success: true, - data: projects - }); + return resolve({ + success: true, + data: projects, + }); + } catch (error) { + return resolve({ + success: false, + data: [], + }); + } + }); + } - } catch (error) { - return resolve({ - success: false, - data: [] - }); - } - }) - } + /** + * Status of tasks. + * @method + * @name tasksStatus + * @param {String} projectId - Project id. + * @param {Array} taskIds - Tasks ids. + * @returns {Object} + */ - /** - * Status of tasks. - * @method - * @name tasksStatus - * @param {String} projectId - Project id. - * @param {Array} taskIds - Tasks ids. - * @returns {Object} - */ + static tasksStatus(projectId, taskIds = []) { + return new Promise(async (resolve, reject) => { + try { + let tasks = await this.tasks(projectId, taskIds); + + if (!tasks.success || !tasks.data.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, + }; + } - static tasksStatus(projectId, taskIds = []) { - return new Promise(async (resolve, reject) => { - try { + let projectTasks = tasks.data[0].tasks; + let result = []; + + for (let task = 0; task < projectTasks.length; task++) { + let currentTask = projectTasks[task]; + + let data = { + type: currentTask.type, + status: currentTask.status, + _id: currentTask._id, + }; + + if ( + currentTask.type === CONSTANTS.common.ASSESSMENT || + currentTask.type === CONSTANTS.common.OBSERVATION + ) { + let completedSubmissionCount = 0; + + let minNoOfSubmissionsRequired = currentTask.solutionDetails + .minNoOfSubmissionsRequired + ? currentTask.solutionDetails.minNoOfSubmissionsRequired + : CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; + + data["submissionStatus"] = CONSTANTS.common.STARTED; + + // For 4.7 Urgent fix, need to check why observationInformation is not present at task level. + let submissionDetails = {}; + if (currentTask.observationInformation) { + submissionDetails = currentTask.observationInformation; + } else if (currentTask.submissionDetails) { + submissionDetails = currentTask.submissionDetails; + } - let tasks = await this.tasks(projectId, taskIds); + data["submissionDetails"] = submissionDetails; - if (!tasks.success || !tasks.data.length > 0) { + if (currentTask.submissions && currentTask.submissions.length > 0) { + let completedSubmissionDoc; + completedSubmissionCount = currentTask.submissions.filter( + (eachSubmission) => + eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS + ).length; - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND - }; - } + if (completedSubmissionCount >= minNoOfSubmissionsRequired) { + completedSubmissionDoc = currentTask.submissions.find( + (eachSubmission) => + eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS + ); + data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; + } else { + completedSubmissionDoc = currentTask.submissions.find( + (eachSubmission) => + eachSubmission.status === CONSTANTS.common.STARTED + ); + } - let projectTasks = tasks.data[0].tasks; - let result = []; + Object.assign(data["submissionDetails"], completedSubmissionDoc); + } else { + data["submissionDetails"].status = CONSTANTS.common.STARTED; + } + } - for (let task = 0; task < projectTasks.length; task++) { + result.push(data); + } - let currentTask = projectTasks[task]; + return resolve({ + success: true, + message: CONSTANTS.apiResponses.TASKS_STATUS_FETCHED, + data: result, + }); + } catch (error) { + return reject({ + success: false, + message: error.message, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + data: [], + }); + } + }); + } - let data = { - type: currentTask.type, - status: currentTask.status, - _id: currentTask._id - }; + /** + * Update task. + * @method + * @name updateTask + * @param {String} projectId - Project id. + * @param {String} taskId - Task id. + * @param {Object} updatedData - Update data. + * @returns {Object} + */ - if ( - currentTask.type === CONSTANTS.common.ASSESSMENT || - currentTask.type === CONSTANTS.common.OBSERVATION - ) { + static pushSubmissionToTask(projectId, taskId, updatedData) { + return new Promise(async (resolve, reject) => { + try { + let updateSubmission = []; + + let projectDocument = await projectQueries.projectDocument( + { + _id: projectId, + "tasks._id": taskId, + }, + ["tasks"] + ); + + let currentTask = projectDocument[0].tasks.find( + (task) => task._id == taskId + ); + let submissions = + currentTask.submissions && currentTask.submissions.length > 0 + ? currentTask.submissions + : []; + + // if submission array is empty + if (!submissions && !submissions.length > 0) { + updateSubmission.push(updatedData); + } - let completedSubmissionCount = 0; + // submission not exist + let checkSubmissionExist = submissions.findIndex( + (submission) => submission._id == updatedData._id + ); - let minNoOfSubmissionsRequired = currentTask.solutionDetails.minNoOfSubmissionsRequired ? currentTask.solutionDetails.minNoOfSubmissionsRequired : CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; + if (checkSubmissionExist == -1) { + updateSubmission = submissions; + updateSubmission.push(updatedData); + } else { + //submission exist + submissions[checkSubmissionExist] = updatedData; + updateSubmission = submissions; + } - data["submissionStatus"] = CONSTANTS.common.STARTED; + let tasksUpdated = await projectQueries.findOneAndUpdate( + { + _id: projectId, + "tasks._id": taskId, + }, + { + $set: { + "tasks.$.submissions": updateSubmission, + }, + } + ); - // For 4.7 Urgent fix, need to check why observationInformation is not present at task level. - let submissionDetails = {}; - if(currentTask.observationInformation) { - submissionDetails = currentTask.observationInformation - } else if (currentTask.submissionDetails) { - submissionDetails = currentTask.submissionDetails - } + return resolve(tasksUpdated); + } catch (error) { + return reject(error); + } + }); + } - data["submissionDetails"] = submissionDetails; - - if ( currentTask.submissions && currentTask.submissions.length > 0 ) { + /** + * Solutions details + * @method + * @name solutionDetails + * @param {String} userToken - Logged in user token. + * @param {String} projectId - Project id. + * @param {Array} taskId - Tasks id. + * @returns {Object} + */ - let completedSubmissionDoc; - completedSubmissionCount = currentTask.submissions.filter((eachSubmission) => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS).length; + static solutionDetails(userToken, projectId, taskId, bodyData = {}) { + return new Promise(async (resolve, reject) => { + try { + let project = await projectQueries.projectDocument( + { + _id: projectId, + "tasks._id": taskId, + }, + [ + "entityInformation._id", + "entityInformation.entityType", + "tasks.type", + "tasks._id", + "tasks.solutionDetails", + "tasks.submissions", + "tasks.observationInformation", + "tasks.externalId", + "programInformation._id", + "projectTemplateId", + ] + ); + if (!project.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND, + }; + } - if (completedSubmissionCount >= minNoOfSubmissionsRequired ) { - - completedSubmissionDoc = currentTask.submissions.find(eachSubmission => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS); - data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; + let currentTask = project[0].tasks.find((task) => task._id == taskId); + + let solutionDetails = currentTask.solutionDetails; + + let assessmentOrObservationData = {}; + + if ( + project[0].entityInformation && + project[0].entityInformation._id && + project[0].programInformation && + project[0].programInformation._id + ) { + assessmentOrObservationData = { + entityId: project[0].entityInformation._id, + programId: project[0].programInformation._id, + }; + + if (currentTask.observationInformation) { + assessmentOrObservationData = currentTask.observationInformation; + } else { + let assessmentOrObservation = { + token: userToken, + solutionDetails: solutionDetails, + entityId: assessmentOrObservationData.entityId, + programId: assessmentOrObservationData.programId, + project: { + _id: projectId, + taskId: taskId, + }, + }; - } else { + let assignedAssessmentOrObservation = + solutionDetails.type === CONSTANTS.common.ASSESSMENT + ? await _assessmentDetails(assessmentOrObservation) + : await _observationDetails(assessmentOrObservation, bodyData); - completedSubmissionDoc = currentTask.submissions.find(eachSubmission => eachSubmission.status === CONSTANTS.common.STARTED); - } + if (!assignedAssessmentOrObservation.success) { + return resolve(assignedAssessmentOrObservation); + } - Object.assign(data["submissionDetails"],completedSubmissionDoc) + assessmentOrObservationData = _.merge( + assessmentOrObservationData, + assignedAssessmentOrObservation.data + ); - } else { + if (!currentTask.solutionDetails.isReusable) { + assessmentOrObservationData["programId"] = + currentTask.solutionDetails.programId; + } - data["submissionDetails"].status = CONSTANTS.common.STARTED; - } - - } + await projectQueries.findOneAndUpdate( + { + _id: projectId, + "tasks._id": taskId, + }, + { + $set: { + "tasks.$.observationInformation": assessmentOrObservationData, + }, + } + ); + } - result.push(data); - } + assessmentOrObservationData["entityType"] = + project[0].entityInformation.entityType; + } - return resolve({ - success: true, - message: CONSTANTS.apiResponses.TASKS_STATUS_FETCHED, - data: result - }); + if ( + currentTask.solutionDetails && + !_.isEmpty(currentTask.solutionDetails) + ) { + assessmentOrObservationData.solutionDetails = + currentTask.solutionDetails; + } - } catch (error) { - return reject({ - success: false, - message: error.message, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - data: [] - }); - } - }) - } + return resolve({ + success: true, + message: CONSTANTS.apiResponses.SOLUTION_DETAILS_FETCHED, + data: assessmentOrObservationData, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); + } - /** - * Update task. - * @method - * @name updateTask - * @param {String} projectId - Project id. - * @param {String} taskId - Task id. - * @param {Object} updatedData - Update data. - * @returns {Object} - */ + /** + * Creation of user targeted projects. + * @method + * @name detailsV2 + * @param {String} projectId - project id. + * @param {String} solutionId - solution id. + * @param {String} userId - logged in user id. + * @param {String} userToken - logged in user token. + * @param {Object} bodyData - Requested body data. + * @param {String} [appName = ""] - App name. + * @param {String} [appVersion = ""] - App version. + * @returns {Object} Project details. + */ - static pushSubmissionToTask(projectId, taskId, updatedData) { - return new Promise(async (resolve, reject) => { - try { - - let updateSubmission = []; - - let projectDocument = await projectQueries.projectDocument( - { - _id: projectId, - "tasks._id": taskId - }, [ - "tasks" - ]); - - let currentTask = projectDocument[0].tasks.find(task => task._id == taskId); - let submissions = currentTask.submissions && currentTask.submissions.length > 0 ? currentTask.submissions : [] ; - - // if submission array is empty - if ( !submissions && !submissions.length > 0 ) { - updateSubmission.push(updatedData); - } - - // submission not exist - let checkSubmissionExist = submissions.findIndex(submission => submission._id == updatedData._id); + static detailsV2( + projectId, + solutionId, + userId, + userToken, + bodyData, + appName = "", + appVersion = "", + templateId = "" + ) { + return new Promise(async (resolve, reject) => { + try { + let solutionExternalId = ""; + + if (templateId !== "") { + let templateDocuments = await projectTemplateQueries.templateDocument( + { + externalId: templateId, + isReusable: false, + solutionId: { $exists: true }, + }, + ["solutionId", "solutionExternalId"] + ); - if ( checkSubmissionExist == -1 ) { + if (!templateDocuments.length > 0) { + throw { + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - updateSubmission = submissions; - updateSubmission.push(updatedData); + solutionId = templateDocuments[0].solutionId; + solutionExternalId = templateDocuments[0].solutionExternalId; + } - } else { - //submission exist - submissions[checkSubmissionExist] = updatedData; - updateSubmission = submissions; + let userRoleInformation = _.omit(bodyData, [ + "referenceFrom", + "submissions", + "hasAcceptedTAndC", + "link", + ]); + + if (projectId === "") { + // This will check wether the user user is targeted to solution or not based on his userRoleInformation + const targetedSolutionId = + await coreService.checkIfSolutionIsTargetedForUserProfile( + userToken, + userRoleInformation, + solutionId + ); + //based on above api will check for projects wether its is private project or public project + const projectDetails = await projectQueries.projectDocument( + { + solutionId: solutionId, + userId: userId, + isAPrivateProgram: targetedSolutionId.data.isATargetedSolution + ? false + : true, + }, + ["_id"] + ); + if (projectDetails.length > 0) { + projectId = projectDetails[0]._id; + } else { + let isAPrivateSolution = + targetedSolutionId.data.isATargetedSolution === false + ? true + : false; + let solutionDetails = {}; + + if (templateId === "") { + // If solution Id of a private program is passed, fetch solution details + if (isAPrivateSolution && solutionId != "") { + solutionDetails = await solutionsHelper.solutionDocuments( + { + _id: solutionId, + isAPrivateProgram: true, + }, + [ + "name", + "externalId", + "description", + "programId", + "programName", + "programDescription", + "programExternalId", + "isAPrivateProgram", + "projectTemplateId", + "entityType", + "entityTypeId", + "language", + "creator", + ] + ); + if (!solutionDetails.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + }; } + solutionDetails = solutionDetails[0]; + } else { + solutionDetails = + await coreService.solutionDetailsBasedOnRoleAndLocation( + userToken, + bodyData, + solutionId, + isAPrivateSolution + ); - let tasksUpdated = await projectQueries.findOneAndUpdate({ - "_id": projectId, - "tasks._id": taskId - }, { - $set: { - "tasks.$.submissions": updateSubmission - } - }); + if ( + !solutionDetails.success || + (solutionDetails.data.data && + !solutionDetails.data.data.length > 0) + ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: + CONSTANTS.apiResponses.SOLUTION_DOES_NOT_EXISTS_IN_SCOPE, + }; + } - return resolve(tasksUpdated); + solutionDetails = solutionDetails.data; + } + } else { + solutionDetails = await surveyService.listSolutions([ + solutionExternalId, + ]); + if (!solutionDetails.success) { + throw { + message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - } catch (error) { - return reject(error); + solutionDetails = solutionDetails.data[0]; } - }) - } - - /** - * Solutions details - * @method - * @name solutionDetails - * @param {String} userToken - Logged in user token. - * @param {String} projectId - Project id. - * @param {Array} taskId - Tasks id. - * @returns {Object} - */ + // check for requestForPIIConsent data + let queryData = {}; + queryData["_id"] = solutionDetails.programId; + let programDetails = await programsQueries.programsDocument( + queryData, + ["requestForPIIConsent"] + ); - static solutionDetails(userToken, projectId, taskId, bodyData = {}) { - return new Promise(async (resolve, reject) => { - try { - - let project = await projectQueries.projectDocument( - { - "_id": projectId, - "tasks._id": taskId - }, [ - "entityInformation._id", - "entityInformation.entityType", - "tasks.type", - "tasks._id", - "tasks.solutionDetails", - "tasks.submissions", - "tasks.observationInformation", - "tasks.externalId", - "programInformation._id", - "projectTemplateId" - ] + // if requestForPIIConsent not there do not call program join + if ( + programDetails.length > 0 && + programDetails[0].hasOwnProperty("requestForPIIConsent") + ) { + // program join API call it will increment the noOfResourcesStarted counter and will make user join program + // before creating any project this api has to called + let programUsers = await programUsersQueries.programUsersDocument( + { + userId: userId, + programId: solutionDetails.programId, + }, + ["_id", "resourcesStarted"] + ); + + if ( + !programUsers.length > 0 || + (programUsers.length > 0 && + programUsers[0].resourcesStarted == false) + ) { + let programJoinBody = {}; + programJoinBody.userRoleInformation = userRoleInformation; + programJoinBody.isResource = true; + programJoinBody.consentShared = true; + let joinProgramData = await coreService.joinProgram( + solutionDetails.programId, + programJoinBody, + userToken ); - if (!project.length > 0) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND - }; + if (!joinProgramData.success) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED, + }); } + } + } + + let projectCreation = await this.userAssignedProjectCreation( + solutionDetails.projectTemplateId, + userId, + userToken + ); - let currentTask = project[0].tasks.find(task => task._id == taskId); - - let solutionDetails = currentTask.solutionDetails; - - let assessmentOrObservationData = {}; - - if (project[0].entityInformation && project[0].entityInformation._id && project[0].programInformation && project[0].programInformation._id) { - - assessmentOrObservationData = { - entityId: project[0].entityInformation._id, - programId: project[0].programInformation._id - } - - if (currentTask.observationInformation) { - assessmentOrObservationData = currentTask.observationInformation; - } else { - - let assessmentOrObservation = { - token: userToken, - solutionDetails: solutionDetails, - entityId: assessmentOrObservationData.entityId, - programId: assessmentOrObservationData.programId, - project: { - "_id": projectId, - "taskId": taskId - } - - }; - - let assignedAssessmentOrObservation = - solutionDetails.type === CONSTANTS.common.ASSESSMENT ? - await _assessmentDetails(assessmentOrObservation) : - await _observationDetails(assessmentOrObservation, bodyData); - - if (!assignedAssessmentOrObservation.success) { - return resolve(assignedAssessmentOrObservation); - } - - assessmentOrObservationData = - _.merge(assessmentOrObservationData, assignedAssessmentOrObservation.data); - - if (!currentTask.solutionDetails.isReusable) { - assessmentOrObservationData["programId"] = - currentTask.solutionDetails.programId; - } - - await projectQueries.findOneAndUpdate({ - "_id": projectId, - "tasks._id": taskId - }, { - $set: { - "tasks.$.observationInformation": assessmentOrObservationData - } - }); - - } - - assessmentOrObservationData["entityType"] = project[0].entityInformation.entityType; + if (!projectCreation.success) { + return resolve(projectCreation); + } - } - - if(currentTask.solutionDetails && !(_.isEmpty(currentTask.solutionDetails))) { + projectCreation.data["isAPrivateProgram"] = + solutionDetails.isAPrivateProgram; - assessmentOrObservationData.solutionDetails = currentTask.solutionDetails; - } + projectCreation.data.programInformation = { + _id: ObjectId(solutionDetails.programId), + externalId: solutionDetails.programExternalId, + description: solutionDetails.programDescription + ? solutionDetails.programDescription + : "", + name: solutionDetails.programName, + }; - return resolve({ - success: true, - message: CONSTANTS.apiResponses.SOLUTION_DETAILS_FETCHED, - data: assessmentOrObservationData - }); + projectCreation.data.solutionInformation = { + _id: ObjectId(solutionDetails._id), + externalId: solutionDetails.externalId, + description: solutionDetails.description + ? solutionDetails.description + : "", + name: solutionDetails.name, + }; + + projectCreation.data["programId"] = + projectCreation.data.programInformation._id; - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} + projectCreation.data["programExternalId"] = + projectCreation.data.programInformation.externalId; + + projectCreation.data["solutionId"] = + projectCreation.data.solutionInformation._id; + + projectCreation.data["solutionExternalId"] = + projectCreation.data.solutionInformation.externalId; + + projectCreation.data["userRole"] = bodyData.role; + + projectCreation.data["appInformation"] = {}; + + if (appName !== "") { + projectCreation.data["appInformation"]["appName"] = appName; + } + + if (appVersion !== "") { + projectCreation.data["appInformation"]["appVersion"] = appVersion; + } + + if ( + solutionDetails.certificateTemplateId && + solutionDetails.certificateTemplateId !== "" + ) { + // <- Add certificate template details to projectCreation data if present -> + const certificateTemplateDetails = + await certificateTemplateQueries.certificateTemplateDocument({ + _id: solutionDetails.certificateTemplateId, }); + + // create certificate object and add data if certificate template is present. + if (certificateTemplateDetails.length > 0) { + projectCreation.data["certificate"] = _.pick( + certificateTemplateDetails[0], + ["templateUrl", "status", "criteria"] + ); + projectCreation.data["certificate"]["templateId"] = + solutionDetails.certificateTemplateId; + } } - }) - } - /** - * Creation of user targeted projects. - * @method - * @name detailsV2 - * @param {String} projectId - project id. - * @param {String} solutionId - solution id. - * @param {String} userId - logged in user id. - * @param {String} userToken - logged in user token. - * @param {Object} bodyData - Requested body data. - * @param {String} [appName = ""] - App name. - * @param {String} [appVersion = ""] - App version. - * @returns {Object} Project details. - */ + let getUserProfileFromObservation = false; + + if (bodyData && Object.keys(bodyData).length > 0) { + if (bodyData.hasAcceptedTAndC) { + projectCreation.data.hasAcceptedTAndC = + bodyData.hasAcceptedTAndC; + } + if (bodyData.link) { + projectCreation.data.link = bodyData.link; + } + + if (bodyData.referenceFrom) { + projectCreation.data.referenceFrom = bodyData.referenceFrom; + + if (bodyData.submissions) { + if ( + bodyData.submissions.observationId && + bodyData.submissions.observationId != "" + ) { + getUserProfileFromObservation = true; + } + projectCreation.data.submissions = bodyData.submissions; + } + } + + if (bodyData.role) { + projectCreation.data["userRole"] = bodyData.role; + } + + if ( + solutionDetails.entityType && + bodyData[solutionDetails.entityType] + ) { + let entityInformation = + await surveyService.listEntitiesByLocationIds(userToken, [ + bodyData[solutionDetails.entityType], + ]); + + if (!entityInformation.success) { + throw { + message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - static detailsV2( projectId,solutionId,userId,userToken,bodyData,appName = "",appVersion = "",templateId = "" ) { - return new Promise(async (resolve, reject) => { - try { - - let solutionExternalId = ""; - - if( templateId !== "" ) { - - let templateDocuments = - await projectTemplateQueries.templateDocument({ - "externalId" : templateId, - "isReusable" : false, - "solutionId" : { $exists : true } - },["solutionId","solutionExternalId"]); - - if( !templateDocuments.length > 0 ) { - throw { - message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } + let entityDetails = await _entitiesMetaInformation( + entityInformation.data + ); + + if (entityDetails && entityDetails.length > 0) { + projectCreation.data["entityInformation"] = entityDetails[0]; } - solutionId = templateDocuments[0].solutionId; - solutionExternalId = templateDocuments[0].solutionExternalId; + projectCreation.data.entityId = entityInformation.data[0]._id; + } } - - let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); - - if (projectId === "") { - // This will check wether the user user is targeted to solution or not based on his userRoleInformation - const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,userRoleInformation,solutionId) - //based on above api will check for projects wether its is private project or public project - const projectDetails = await projectQueries.projectDocument({ - solutionId: solutionId, - userId: userId, - isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true - }, ["_id"]); - if( projectDetails.length > 0 ) { - projectId = projectDetails[0]._id; - } else { - let isAPrivateSolution = (targetedSolutionId.data.isATargetedSolution === false) ? true : false; - let solutionDetails = {} - - if( templateId === "" ) { - // If solution Id of a private program is passed, fetch solution details - if ( isAPrivateSolution && solutionId != "" ) { - solutionDetails = await solutionsHelper.solutionDocuments({ - _id: solutionId, - isAPrivateProgram: true - }, - [ - "name", - "externalId", - "description", - "programId", - "programName", - "programDescription", - "programExternalId", - "isAPrivateProgram", - "projectTemplateId", - "entityType", - "entityTypeId", - "language", - "creator" - ]); - if( !solutionDetails.length > 0 ) { - throw { - status : HTTP_STATUS_CODE["bad_request"].status, - message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND - } - } - solutionDetails = solutionDetails[0]; - } else { - solutionDetails = - await coreService.solutionDetailsBasedOnRoleAndLocation( - userToken, - bodyData, - solutionId, - isAPrivateSolution - ); - - if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { - throw { - status : HTTP_STATUS_CODE["bad_request"].status, - message : CONSTANTS.apiResponses.SOLUTION_DOES_NOT_EXISTS_IN_SCOPE - } - } - - solutionDetails = solutionDetails.data; - } - - } else { - - solutionDetails = - await surveyService.listSolutions([solutionExternalId]); - if( !solutionDetails.success ) { - throw { - message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - solutionDetails = solutionDetails.data[0]; - - } - // check for requestForPIIConsent data - let queryData = {}; - queryData["_id"] = solutionDetails.programId; - let programDetails = await programsQueries.programsDocument(queryData,["requestForPIIConsent"]); - - // if requestForPIIConsent not there do not call program join - if ( programDetails.length > 0 && programDetails[0].hasOwnProperty('requestForPIIConsent')) { - - // program join API call it will increment the noOfResourcesStarted counter and will make user join program - // before creating any project this api has to called - let programUsers = await programUsersQueries.programUsersDocument( - { - userId : userId, - programId : solutionDetails.programId - }, - [ - "_id", - "resourcesStarted" - ] - ); - - if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { - let programJoinBody = {}; - programJoinBody.userRoleInformation = userRoleInformation; - programJoinBody.isResource = true; - programJoinBody.consentShared = true; - let joinProgramData = await coreService.joinProgram ( - solutionDetails.programId, - programJoinBody, - userToken - ); - if ( !joinProgramData.success ) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - }); - } - } - } - - let projectCreation = - await this.userAssignedProjectCreation( - solutionDetails.projectTemplateId, - userId, - userToken - ); - if( !projectCreation.success ) { - return resolve(projectCreation); - } - - projectCreation.data["isAPrivateProgram"] = - solutionDetails.isAPrivateProgram; - - projectCreation.data.programInformation = { - _id : ObjectId(solutionDetails.programId), - externalId : solutionDetails.programExternalId, - description : - solutionDetails.programDescription ? solutionDetails.programDescription : "", - name : solutionDetails.programName - } - - projectCreation.data.solutionInformation = { - _id : ObjectId(solutionDetails._id), - externalId : solutionDetails.externalId, - description : - solutionDetails.description ? - solutionDetails.description : "", - name : solutionDetails.name - }; - - projectCreation.data["programId"] = - projectCreation.data.programInformation._id; - - projectCreation.data["programExternalId"] = - projectCreation.data.programInformation.externalId; - - projectCreation.data["solutionId"] = - projectCreation.data.solutionInformation._id; - - projectCreation.data["solutionExternalId"] = - projectCreation.data.solutionInformation.externalId; - - projectCreation.data["userRole"] = - bodyData.role; - - projectCreation.data["appInformation"] = {}; - - if( appName !== "" ) { - projectCreation.data["appInformation"]["appName"] = appName; - } - - if( appVersion !== "" ) { - projectCreation.data["appInformation"]["appVersion"] = appVersion; - } - - if ( solutionDetails.certificateTemplateId && solutionDetails.certificateTemplateId !== "" ) { - // <- Add certificate template details to projectCreation data if present -> - const certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : solutionDetails.certificateTemplateId - }); - - // create certificate object and add data if certificate template is present. - if ( certificateTemplateDetails.length > 0 ) { - projectCreation.data["certificate"] = _.pick(certificateTemplateDetails[0], ['templateUrl', 'status', 'criteria']); - projectCreation.data["certificate"]["templateId"] = solutionDetails.certificateTemplateId; - } - } - - let getUserProfileFromObservation = false; - - if( bodyData && Object.keys(bodyData).length > 0 ) { - - if( bodyData.hasAcceptedTAndC ) { - projectCreation.data.hasAcceptedTAndC = bodyData.hasAcceptedTAndC; - } - if( bodyData.link ) { - projectCreation.data.link = bodyData.link; - } - - if( bodyData.referenceFrom ) { - projectCreation.data.referenceFrom = bodyData.referenceFrom; - - if( bodyData.submissions ) { - if ( bodyData.submissions.observationId && bodyData.submissions.observationId != "" ) { - getUserProfileFromObservation = true; - } - projectCreation.data.submissions = bodyData.submissions; - } - } - - if( bodyData.role ) { - projectCreation.data["userRole"] = bodyData.role; - } - - if( - solutionDetails.entityType && bodyData[solutionDetails.entityType] - ) { - let entityInformation = - await surveyService.listEntitiesByLocationIds( - userToken, - [bodyData[solutionDetails.entityType]] - ); - - if( !entityInformation.success ) { - throw { - message : CONSTANTS.apiResponses.ENTITY_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - let entityDetails = await _entitiesMetaInformation( - entityInformation.data - ); - - if ( entityDetails && entityDetails.length > 0 ) { - projectCreation.data["entityInformation"] = entityDetails[0]; - } - - projectCreation.data.entityId = entityInformation.data[0]._id; - } - - } - - projectCreation.data.status = CONSTANTS.common.STARTED; - projectCreation.data.lastDownloadedAt = new Date(); - - // fetch userRoleInformation from observation if referenecFrom is observation - let addReportInfoToSolution = false; - if ( getUserProfileFromObservation ){ - - let observationDetails = await surveyService.observationDetails( - userToken, - bodyData.submissions.observationId - ); - - if( observationDetails.data && - Object.keys(observationDetails.data).length > 0 && - observationDetails.data.userRoleInformation && - Object.keys(observationDetails.data.userRoleInformation).length > 0 - ) { - - userRoleInformation = observationDetails.data.userRoleInformation; - - } - - if( observationDetails.data && - Object.keys(observationDetails.data).length > 0 && - observationDetails.data.userProfile && - Object.keys(observationDetails.data.userProfile).length > 0 - ) { - - projectCreation.data.userProfile = observationDetails.data.userProfile; - addReportInfoToSolution = true; - - } else { - //Fetch user profile information by calling sunbird's user read api. - - let userProfile = await userProfileService.profile(userToken, userId); - if ( userProfile.success && - userProfile.data && - userProfile.data.response - ) { - projectCreation.data.userProfile = userProfile.data.response; - addReportInfoToSolution = true; - } - } - - } else { - //Fetch user profile information by calling sunbird's user read api. - - let userProfileData = await userProfileService.profile(userToken, userId); - if ( userProfileData.success && - userProfileData.data && - userProfileData.data.response - ) { - projectCreation.data.userProfile = userProfileData.data.response; - addReportInfoToSolution = true; - } - } - - projectCreation.data.userRoleInformation = userRoleInformation; - - //compare & update userProfile with userRoleInformation - if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { - let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( - projectCreation.data.userProfile, - userRoleInformation - ); - - if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { - projectCreation.data.userProfile = updatedUserProfile.data; - } - } - - let project = await projectQueries.createProject(projectCreation.data); - - if ( addReportInfoToSolution && project.solutionId ) { - let updateSolution = await solutionsHelper.addReportInformationInSolution( - project.solutionId, - project.userProfile - ); - } - - await kafkaProducersHelper.pushProjectToKafka(project); - - projectId = project._id; + projectCreation.data.status = CONSTANTS.common.STARTED; + projectCreation.data.lastDownloadedAt = new Date(); + + // fetch userRoleInformation from observation if referenecFrom is observation + let addReportInfoToSolution = false; + if (getUserProfileFromObservation) { + let observationDetails = await surveyService.observationDetails( + userToken, + bodyData.submissions.observationId + ); + + if ( + observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userRoleInformation && + Object.keys(observationDetails.data.userRoleInformation) + .length > 0 + ) { + userRoleInformation = + observationDetails.data.userRoleInformation; + } + + if ( + observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userProfile && + Object.keys(observationDetails.data.userProfile).length > 0 + ) { + projectCreation.data.userProfile = + observationDetails.data.userProfile; + addReportInfoToSolution = true; + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfile = await userProfileService.profile( + userToken, + userId + ); + if ( + userProfile.success && + userProfile.data && + userProfile.data.response + ) { + projectCreation.data.userProfile = userProfile.data.response; + addReportInfoToSolution = true; } + } + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfileData = await userProfileService.profile( + userToken, + userId + ); + if ( + userProfileData.success && + userProfileData.data && + userProfileData.data.response + ) { + projectCreation.data.userProfile = + userProfileData.data.response; + addReportInfoToSolution = true; + } + } + + projectCreation.data.userRoleInformation = userRoleInformation; + + //compare & update userProfile with userRoleInformation + if ( + projectCreation.data.userProfile && + userRoleInformation && + Object.keys(userRoleInformation).length > 0 && + Object.keys(projectCreation.data.userProfile).length > 0 + ) { + let updatedUserProfile = + await _updateUserProfileBasedOnUserRoleInfo( + projectCreation.data.userProfile, + userRoleInformation + ); + + if ( + updatedUserProfile && + updatedUserProfile.success == true && + updatedUserProfile.profileMismatchFound == true + ) { + projectCreation.data.userProfile = updatedUserProfile.data; + } } - let projectDetails = await this.details( - projectId, - userId, - userRoleInformation + let project = await projectQueries.createProject( + projectCreation.data ); - - let revertStatusorNot = UTILS.revertStatusorNot(appVersion); - if ( revertStatusorNot ) { - projectDetails.data.status = UTILS.revertProjectStatus(projectDetails.data.status); - } else { - projectDetails.data.status = UTILS.convertProjectStatus(projectDetails.data.status); + + if (addReportInfoToSolution && project.solutionId) { + let updateSolution = + await solutionsHelper.addReportInformationInSolution( + project.solutionId, + project.userProfile + ); } - // make templateUrl downloadable befor passing to front-end - if ( projectDetails.data.certificate && - projectDetails.data.certificate.templateUrl && - projectDetails.data.certificate.templateUrl !== "" - ) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: [projectDetails.data.certificate.templateUrl] - } - ); - if ( certificateTemplateDownloadableUrl.success ) { - projectDetails.data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; - } - } - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, - data: projectDetails.data - }); - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] + await kafkaProducersHelper.pushProjectToKafka(project); + + projectId = project._id; + } + } + + let projectDetails = await this.details( + projectId, + userId, + userRoleInformation + ); + + let revertStatusorNot = UTILS.revertStatusorNot(appVersion); + if (revertStatusorNot) { + projectDetails.data.status = UTILS.revertProjectStatus( + projectDetails.data.status + ); + } else { + projectDetails.data.status = UTILS.convertProjectStatus( + projectDetails.data.status + ); + } + // make templateUrl downloadable befor passing to front-end + if ( + projectDetails.data.certificate && + projectDetails.data.certificate.templateUrl && + projectDetails.data.certificate.templateUrl !== "" + ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl({ + filePaths: [projectDetails.data.certificate.templateUrl], }); + if (certificateTemplateDownloadableUrl.success) { + projectDetails.data.certificate.templateUrl = + certificateTemplateDownloadableUrl.data[0].url; + } } - }) -} - /** + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, + data: projectDetails.data, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: [], + }); + } + }); + } + + /** * User assigned project creation data. * @method * @name userAssignedProjectCreation @@ -1547,2504 +1726,2714 @@ module.exports = class UserProjectsHelper { * @returns {String} - message. */ - static userAssignedProjectCreation(templateId, userId, userToken) { - return new Promise(async (resolve, reject) => { - try { - const projectTemplateData = - await projectTemplateQueries.templateDocument({ - status: CONSTANTS.common.PUBLISHED, - _id: templateId, - isReusable: false - }, "all", - [ - "ratings", - "noOfRatings", - "averageRating" - ]); - - if (!projectTemplateData.length > 0) { - throw { - message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - let result = { ...projectTemplateData[0] }; - - result.projectTemplateId = result._id; - result.projectTemplateExternalId = result.externalId; - result.userId = userId; - result.createdBy = userId; - result.updatedBy = userId; - - result.createdAt = new Date(); - result.updatedAt = new Date(); - - result.assesmentOrObservationTask = false; - - if (projectTemplateData[0].tasks && projectTemplateData[0].tasks.length > 0) { - - const tasksAndSubTasks = - await projectTemplatesHelper.tasksAndSubTasks( - projectTemplateData[0]._id - ); - - if (tasksAndSubTasks.length > 0) { + static userAssignedProjectCreation(templateId, userId, userToken) { + return new Promise(async (resolve, reject) => { + try { + const projectTemplateData = + await projectTemplateQueries.templateDocument( + { + status: CONSTANTS.common.PUBLISHED, + _id: templateId, + isReusable: false, + }, + "all", + ["ratings", "noOfRatings", "averageRating"] + ); + + if (!projectTemplateData.length > 0) { + throw { + message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - result.tasks = _projectTask(tasksAndSubTasks); - result.tasks.forEach(task => { - if ( - task.type === CONSTANTS.common.ASSESSMENT || - task.type === CONSTANTS.common.OBSERVATION - ) { - result.assesmentOrObservationTask = true; - } - }); + let result = { ...projectTemplateData[0] }; + result.projectTemplateId = result._id; + result.projectTemplateExternalId = result.externalId; + result.userId = userId; + result.createdBy = userId; + result.updatedBy = userId; - let taskReport = { - total: result.tasks.length - }; + result.createdAt = new Date(); + result.updatedAt = new Date(); - result.tasks.forEach(task => { - if ( task.isDeleted == false ) { + result.assesmentOrObservationTask = false; - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } + if ( + projectTemplateData[0].tasks && + projectTemplateData[0].tasks.length > 0 + ) { + const tasksAndSubTasks = + await projectTemplatesHelper.tasksAndSubTasks( + projectTemplateData[0]._id + ); - } else { - taskReport.total = taskReport.total - 1; - } - - }); + if (tasksAndSubTasks.length > 0) { + result.tasks = _projectTask(tasksAndSubTasks); + result.tasks.forEach((task) => { + if ( + task.type === CONSTANTS.common.ASSESSMENT || + task.type === CONSTANTS.common.OBSERVATION + ) { + result.assesmentOrObservationTask = true; + } + }); - result["taskReport"] = taskReport; + let taskReport = { + total: result.tasks.length, + }; - } + result.tasks.forEach((task) => { + if (task.isDeleted == false) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; } + } else { + taskReport.total = taskReport.total - 1; + } + }); - delete result._id; + result["taskReport"] = taskReport; + } + } - return resolve({ - success: true, - message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, - data: result - }); + delete result._id; - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); - } + return resolve({ + success: true, + message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, + data: result, }); - } - - /** - * Add project. - * @method - * @name add - * @param {Object} data - body data. - * @param {String} userId - Logged in user id. - * @param {String} userToken - User token. - * @param {String} [appName = ""] - App Name. - * @param {String} [appVersion = ""] - App Version. - * @returns {Object} Project created information. - */ - - static add(data, userId, userToken, appName = "", appVersion = "") { - return new Promise(async (resolve, reject) => { - try { - const projectsModel = Object.keys(schemas["projects"].schema); - let createProject = {}; - - createProject["userId"] = createProject["createdBy"] = createProject["updatedBy"] = userId; - - //Fetch user profile information by calling sunbird's user read api. - - let userProfile = await userProfileService.profile(userToken, userId); - if ( userProfile.success && - userProfile.data && - userProfile.data.response - ) { - createProject.userProfile = userProfile.data.response; - } - - - - let projectData = await _projectData(data); - if (projectData && projectData.success == true) { - createProject = _.merge(createProject, projectData.data); - } - - let createNewProgramAndSolution = false; - - if (data.programId && data.programId !== "") { - createNewProgramAndSolution = false; - } - else if (data.programName) { - createNewProgramAndSolution = true; - } - - if (data.entityId) { - let entityInformation = - await _entitiesInformation([data.entityId]); - - if (!entityInformation.success) { - return resolve(entityInformation); - } - - createProject["entityInformation"] = entityInformation.data[0]; - createProject.entityId = entityInformation.data[0]._id; - } - if (createNewProgramAndSolution) { - - let programAndSolutionInformation = - await this.createProgramAndSolution( - data.programId, - data.programName, - createProject.entityId ? [createProject.entityId] : "", - userToken - ); - - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } - createProject = - _.merge(createProject, programAndSolutionInformation.data); - } - - if (data.programId && data.programId !== "") { - - let queryData = {}; - queryData["_id"] = data.programId; - let programDetails = await programsQueries.programsDocument(queryData, - [ - "_id", - "name", - "description", - "isAPrivateProgram" - ] - ); - if( !programDetails.length > 0 ){ - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND - }; - } - let programInformationData = {}; - programInformationData["programInformation"] = programDetails[0]; - createProject = - _.merge(createProject, programInformationData); - } - + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); + } - if (data.tasks) { + /** + * Add project. + * @method + * @name add + * @param {Object} data - body data. + * @param {String} userId - Logged in user id. + * @param {String} userToken - User token. + * @param {String} [appName = ""] - App Name. + * @param {String} [appVersion = ""] - App Version. + * @returns {Object} Project created information. + */ - let taskReport = {}; + static add(data, userId, userToken, appName = "", appVersion = "") { + return new Promise(async (resolve, reject) => { + try { + const projectsModel = Object.keys(schemas["projects"].schema); + let createProject = {}; + + createProject["userId"] = + createProject["createdBy"] = + createProject["updatedBy"] = + userId; + + //Fetch user profile information by calling sunbird's user read api. + + let userProfile = await userProfileService.profile(userToken, userId); + if ( + userProfile.success && + userProfile.data && + userProfile.data.response + ) { + createProject.userProfile = userProfile.data.response; + } - createProject.tasks = await _projectTask( - data.tasks - ); + let projectData = await _projectData(data); + if (projectData && projectData.success == true) { + createProject = _.merge(createProject, projectData.data); + } - taskReport.total = createProject.tasks.length; - - createProject.tasks.forEach(task => { - if ( task.isDeleted == false ) { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - } else { - //if task is deleted it is not counted in total. - taskReport.total = taskReport.total - 1; - } - - }); - - createProject["taskReport"] = taskReport; - } + let createNewProgramAndSolution = false; - let booleanData = this.booleanData(schemas["projects"].schema); - let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); + if (data.programId && data.programId !== "") { + createNewProgramAndSolution = false; + } else if (data.programName) { + createNewProgramAndSolution = true; + } + if (data.entityId) { + let entityInformation = await _entitiesInformation([data.entityId]); - Object.keys(data).forEach(updateData => { - if ( - !createProject[updateData] && - projectsModel.includes(updateData) - ) { + if (!entityInformation.success) { + return resolve(entityInformation); + } - if (booleanData.includes(updateData)) { + createProject["entityInformation"] = entityInformation.data[0]; + createProject.entityId = entityInformation.data[0]._id; + } + if (createNewProgramAndSolution) { + let programAndSolutionInformation = + await this.createProgramAndSolution( + data.programId, + data.programName, + createProject.entityId ? [createProject.entityId] : "", + userToken + ); - createProject[updateData] = - UTILS.convertStringToBoolean(data[updateData]); + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + createProject = _.merge( + createProject, + programAndSolutionInformation.data + ); + } - } else if (mongooseIdData.includes(updateData)) { - createProject[updateData] = ObjectId(data[updateData]); - } else { - createProject[updateData] = data[updateData]; - } - } - }); + if (data.programId && data.programId !== "") { + let queryData = {}; + queryData["_id"] = data.programId; + let programDetails = await programsQueries.programsDocument( + queryData, + ["_id", "name", "description", "isAPrivateProgram"] + ); + if (!programDetails.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND, + }; + } + let programInformationData = {}; + programInformationData["programInformation"] = programDetails[0]; + createProject = _.merge(createProject, programInformationData); + } - createProject["appInformation"] = {}; - if (appName !== "") { - createProject["appInformation"]["appName"] = appName; - } + if (data.tasks) { + let taskReport = {}; - if (appVersion !== "") { - createProject["appInformation"]["appVersion"] = appVersion; - } + createProject.tasks = await _projectTask(data.tasks); - createProject["lastDownloadedAt"] = new Date(); + taskReport.total = createProject.tasks.length; - if (data.profileInformation) { - createProject.userRoleInformation = data.profileInformation; - } + createProject.tasks.forEach((task) => { + if (task.isDeleted == false) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + } else { + //if task is deleted it is not counted in total. + taskReport.total = taskReport.total - 1; + } + }); - createProject.status = UTILS.convertProjectStatus(data.status); - let userProject = await projectQueries.createProject( - createProject - ); - - await kafkaProducersHelper.pushProjectToKafka(userProject); - - if (!userProject._id) { - throw { - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_CREATED, - status: HTTP_STATUS_CODE['bad_request'].status - } - } + createProject["taskReport"] = taskReport; + } - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_CREATED, - data: { - programId: - userProject.programInformation && userProject.programInformation._id ? - userProject.programInformation._id : data.programId, - projectId: userProject._id, - lastDownloadedAt: userProject.lastDownloadedAt, - hasAcceptedTAndC : userProject.hasAcceptedTAndC ? userProject.hasAcceptedTAndC : false - } - }); - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); + let booleanData = this.booleanData(schemas["projects"].schema); + let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); + + Object.keys(data).forEach((updateData) => { + if ( + !createProject[updateData] && + projectsModel.includes(updateData) + ) { + if (booleanData.includes(updateData)) { + createProject[updateData] = UTILS.convertStringToBoolean( + data[updateData] + ); + } else if (mongooseIdData.includes(updateData)) { + createProject[updateData] = ObjectId(data[updateData]); + } else { + createProject[updateData] = data[updateData]; } - }) - } - + } + }); - /** - * share project and task pdf report. - * @method - * @name share - * @param {String} [projectId] - projectId. - * @returns {Object} Downloadable pdf url. - */ + createProject["appInformation"] = {}; + if (appName !== "") { + createProject["appInformation"]["appName"] = appName; + } - static share(projectId = "", taskIds = [], userToken,appVersion) { - return new Promise(async (resolve, reject) => { - try { + if (appVersion !== "") { + createProject["appInformation"]["appVersion"] = appVersion; + } - let projectPdf = true; - let projectDocument = []; + createProject["lastDownloadedAt"] = new Date(); - let query = { - _id: projectId, - isDeleted: false - } + if (data.profileInformation) { + createProject.userRoleInformation = data.profileInformation; + } - if (!taskIds.length ) { - - projectDocument = await projectQueries.projectDocument - ( - query, - [ - "title", - "status", - "metaInformation.goal", - "metaInformation.duration", - "startDate", - "description", - "endDate", - "tasks", - "categories", - "programInformation.name", - "recommendedFor", - "link", - "remarks", - "attachments", - "taskReport.completed" - ] - ); - } - else { - projectPdf = false; - - let aggregateData = [ - { "$match": { _id: ObjectId(projectId), isDeleted: false} }, - { "$project": { - "status": 1, "title": 1, "startDate": 1, "metaInformation.goal": 1, "metaInformation.duration":1, - "categories" : 1, "programInformation.name": 1, "description" : 1, "recommendedFor" : 1, "link" : 1, "remarks" : 1, "attachments" : 1, "taskReport.completed" : 1, - tasks: { "$filter": { - input: '$tasks', - as: 'tasks', - cond: { "$in": ['$$tasks._id', taskIds]} - }} - }}] - - projectDocument = await projectQueries.getAggregate(aggregateData); - } - - if (!projectDocument.length) { - throw { - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - } - } + createProject.status = UTILS.convertProjectStatus(data.status); + let userProject = await projectQueries.createProject(createProject); - projectDocument = projectDocument[0]; - projectDocument.goal = projectDocument.metaInformation ? projectDocument.metaInformation.goal : ""; - projectDocument.duration = projectDocument.metaInformation ? projectDocument.metaInformation.duration : ""; - projectDocument.programName = projectDocument.programInformation ? projectDocument.programInformation.name : ""; - projectDocument.remarks = projectDocument.remarks ? projectDocument.remarks : ""; - projectDocument.taskcompleted = projectDocument.taskReport.completed ? projectDocument.taskReport.completed : CONSTANTS.common.DEFAULT_TASK_COMPLETED; - - //store tasks and attachment data into object - let projectFilter = { - tasks : projectDocument.tasks, - attachments : projectDocument.attachments - } - - //returns project tasks and attachments with downloadable urls - let projectDataWithUrl = await _projectInformation( projectFilter ); - - //replace projectDocument Data - if ( projectDataWithUrl.success && - projectDataWithUrl.data && - projectDataWithUrl.data.tasks && - projectDataWithUrl.data.tasks.length > 0 - ) { - - projectDocument.tasks = projectDataWithUrl.data.tasks ; - } + await kafkaProducersHelper.pushProjectToKafka(userProject); - if ( projectDataWithUrl.success && - projectDataWithUrl.data && - projectDataWithUrl.data.attachments && - projectDataWithUrl.data.attachments.length > 0 - ) { - projectDocument.attachments = projectDataWithUrl.data.attachments ; - } - - - //get image link and other document links - let imageLink = []; - let evidenceLink = []; - if ( projectDocument.attachments && projectDocument.attachments.length > 0 ) { - projectDocument.attachments.forEach( attachment => { - if( attachment.type == CONSTANTS.common.IMAGE_DATA_TYPE && attachment.url && attachment.url !== "" ) { - imageLink.push( attachment.url ); - } else if ( attachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK && attachment.name && attachment.name !== "" ) { - let data = { - type : attachment.type, - url : attachment.name - } - evidenceLink.push( data ); - } else if ( attachment.url && attachment.url !== "" ) { - let data = { - type : attachment.type, - url : attachment.url - } - evidenceLink.push( data ); - } - }) - } - projectDocument.evidenceLink = evidenceLink; - projectDocument.imageLink = imageLink; - - projectDocument.category = []; - - if (projectDocument.categories && projectDocument.categories.length > 0) { - projectDocument.categories.forEach( category => { - projectDocument.category.push(category.name); - }) - } + if (!userProject._id) { + throw { + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_CREATED, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - projectDocument.recommendedForRoles = []; + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_CREATED, + data: { + programId: + userProject.programInformation && + userProject.programInformation._id + ? userProject.programInformation._id + : data.programId, + projectId: userProject._id, + lastDownloadedAt: userProject.lastDownloadedAt, + hasAcceptedTAndC: userProject.hasAcceptedTAndC + ? userProject.hasAcceptedTAndC + : false, + }, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); + } - if (projectDocument.recommendedFor && projectDocument.recommendedFor.length > 0) { - projectDocument.recommendedFor.forEach( recommend => { - projectDocument.recommendedForRoles.push(recommend.code); - }) - } - - let tasks = []; - if (projectDocument.tasks.length > 0) { - projectDocument.tasks.forEach( task => { - let subtasks = []; - if (!task.isDeleted) { - if (task.children.length > 0) { - task.children.forEach(children => { - if (!children.isDeleted) { - subtasks.push(children); - } - }) - } - task.children = subtasks; - tasks.push(task); - } - }) - projectDocument.tasks = tasks; - } + /** + * share project and task pdf report. + * @method + * @name share + * @param {String} [projectId] - projectId. + * @returns {Object} Downloadable pdf url. + */ - delete projectDocument.categories; - delete projectDocument.metaInformation; - delete projectDocument.programInformation; - delete projectDocument.recommendedFor; - - if (UTILS.revertStatusorNot(appVersion)) { - projectDocument.status = UTILS.revertProjectStatus(projectDocument.status); - } - let response = await reportService.projectAndTaskReport(userToken, projectDocument, projectPdf); - - if (response && response.success == true) { - return resolve({ - success: true, - message: CONSTANTS.apiResponses.REPORT_GENERATED_SUCCESSFULLY, - data: { - data: { - downloadUrl: response.data.pdfUrl - } - } - }); - } + static share(projectId = "", taskIds = [], userToken, appVersion) { + return new Promise(async (resolve, reject) => { + try { + let projectPdf = true; + let projectDocument = []; + + let query = { + _id: projectId, + isDeleted: false, + }; + + if (!taskIds.length) { + projectDocument = await projectQueries.projectDocument(query, [ + "title", + "status", + "metaInformation.goal", + "metaInformation.duration", + "startDate", + "description", + "endDate", + "tasks", + "categories", + "programInformation.name", + "recommendedFor", + "link", + "remarks", + "attachments", + "taskReport.completed", + ]); + } else { + projectPdf = false; + + let aggregateData = [ + { $match: { _id: ObjectId(projectId), isDeleted: false } }, + { + $project: { + status: 1, + title: 1, + startDate: 1, + "metaInformation.goal": 1, + "metaInformation.duration": 1, + categories: 1, + "programInformation.name": 1, + description: 1, + recommendedFor: 1, + link: 1, + remarks: 1, + attachments: 1, + "taskReport.completed": 1, + tasks: { + $filter: { + input: "$tasks", + as: "tasks", + cond: { $in: ["$$tasks._id", taskIds] }, + }, + }, + }, + }, + ]; - else { - throw { - message: CONSTANTS.apiResponses.COULD_NOT_GENERATE_PDF_REPORT, - } - } + projectDocument = await projectQueries.getAggregate(aggregateData); + } - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: {} - }); - } - }) - } + if (!projectDocument.length) { + throw { + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - /** - * Get list of user projects with the targetted ones. - * @method - * @name userAssigned - * @param {String} userId - Logged in user id. - * @param {Number} pageSize - Page size. - * @param {Number} pageNo - Page No. - * @param {String} search - Search text. - * @param {String} filter - filter text. - * @returns {Object} - */ + projectDocument = projectDocument[0]; + projectDocument.goal = projectDocument.metaInformation + ? projectDocument.metaInformation.goal + : ""; + projectDocument.duration = projectDocument.metaInformation + ? projectDocument.metaInformation.duration + : ""; + projectDocument.programName = projectDocument.programInformation + ? projectDocument.programInformation.name + : ""; + projectDocument.remarks = projectDocument.remarks + ? projectDocument.remarks + : ""; + projectDocument.taskcompleted = projectDocument.taskReport.completed + ? projectDocument.taskReport.completed + : CONSTANTS.common.DEFAULT_TASK_COMPLETED; + + //store tasks and attachment data into object + let projectFilter = { + tasks: projectDocument.tasks, + attachments: projectDocument.attachments, + }; + + //returns project tasks and attachments with downloadable urls + let projectDataWithUrl = await _projectInformation(projectFilter); + + //replace projectDocument Data + if ( + projectDataWithUrl.success && + projectDataWithUrl.data && + projectDataWithUrl.data.tasks && + projectDataWithUrl.data.tasks.length > 0 + ) { + projectDocument.tasks = projectDataWithUrl.data.tasks; + } - static userAssigned( userId,pageSize,pageNo,search, filter ) { - return new Promise(async (resolve, reject) => { - try { + if ( + projectDataWithUrl.success && + projectDataWithUrl.data && + projectDataWithUrl.data.attachments && + projectDataWithUrl.data.attachments.length > 0 + ) { + projectDocument.attachments = projectDataWithUrl.data.attachments; + } - let query = { - userId : userId, - isDeleted : false + //get image link and other document links + let imageLink = []; + let evidenceLink = []; + if ( + projectDocument.attachments && + projectDocument.attachments.length > 0 + ) { + projectDocument.attachments.forEach((attachment) => { + if ( + attachment.type == CONSTANTS.common.IMAGE_DATA_TYPE && + attachment.url && + attachment.url !== "" + ) { + imageLink.push(attachment.url); + } else if ( + attachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK && + attachment.name && + attachment.name !== "" + ) { + let data = { + type: attachment.type, + url: attachment.name, + }; + evidenceLink.push(data); + } else if (attachment.url && attachment.url !== "") { + let data = { + type: attachment.type, + url: attachment.url, + }; + evidenceLink.push(data); } + }); + } + projectDocument.evidenceLink = evidenceLink; + projectDocument.imageLink = imageLink; + + projectDocument.category = []; + + if ( + projectDocument.categories && + projectDocument.categories.length > 0 + ) { + projectDocument.categories.forEach((category) => { + projectDocument.category.push(category.name); + }); + } - let searchQuery = []; + projectDocument.recommendedForRoles = []; - if (search !== "") { - searchQuery = [ - { "title" : new RegExp(search, 'i') }, - { "description" : new RegExp(search, 'i') } - ]; - } + if ( + projectDocument.recommendedFor && + projectDocument.recommendedFor.length > 0 + ) { + projectDocument.recommendedFor.forEach((recommend) => { + projectDocument.recommendedForRoles.push(recommend.code); + }); + } - if ( filter && filter !== "" ) { - if( filter === CONSTANTS.common.CREATED_BY_ME ) { - query["referenceFrom"] = { - $ne : CONSTANTS.common.LINK - }; - query["isAPrivateProgram"] = { - $ne : false - }; - } else if( filter == CONSTANTS.common.ASSIGN_TO_ME ) { - query["isAPrivateProgram"] = false; - } else{ - query["referenceFrom"] = CONSTANTS.common.LINK; - } + let tasks = []; + if (projectDocument.tasks.length > 0) { + projectDocument.tasks.forEach((task) => { + let subtasks = []; + if (!task.isDeleted) { + if (task.children.length > 0) { + task.children.forEach((children) => { + if (!children.isDeleted) { + subtasks.push(children); + } + }); + } + task.children = subtasks; + tasks.push(task); } - - let projects = await this.projects( - query, - pageSize, - pageNo, - searchQuery, - [ - "title", - "description", - "solutionId", - "programId", - "programInformation.name", - "projectTemplateId", - "solutionExternalId", - "lastDownloadedAt", - "hasAcceptedTAndC", - "referenceFrom", - "status", - "certificate" - ] - ); - - let totalCount = 0; - let data = []; - if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { - - totalCount = projects.data.count; - data = projects.data.data; - - if( data.length > 0 ) { - let templateFilePath = []; - data.forEach( projectData => { - - projectData.name = projectData.title; - - - if (projectData.programInformation) { - projectData.programName = projectData.programInformation.name; - delete projectData.programInformation; - } - - if (projectData.solutionExternalId) { - projectData.externalId = projectData.solutionExternalId; - delete projectData.solutionExternalId; - } - - projectData.type = CONSTANTS.common.IMPROVEMENT_PROJECT; - delete projectData.title; - - if (projectData.certificate && - projectData.certificate.osid && - projectData.certificate.osid !== "" && - projectData.certificate.templateUrl && - projectData.certificate.templateUrl !== "" - ) { - templateFilePath.push(projectData.certificate.templateUrl); - } - - }); - - if( templateFilePath.length > 0 ) { - - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: templateFilePath - } - ); - if ( !certificateTemplateDownloadableUrl.success ) { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND - }; - } - // map downloadable templateUrl to corresponding project data - data.forEach(projectData => { - if (projectData.certificate) { - var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find(item=> item.filePath == projectData.certificate.templateUrl); - if (itemFromUrlArray) { - projectData.certificate.templateUrl = itemFromUrlArray.url; - } - } - } - - ) - } + }); + projectDocument.tasks = tasks; + } - } - } - - return resolve({ - success : true, - message : CONSTANTS.apiResponses.USER_ASSIGNED_PROJECT_FETCHED, - data : { - data: data, - count: totalCount - } - }); + delete projectDocument.categories; + delete projectDocument.metaInformation; + delete projectDocument.programInformation; + delete projectDocument.recommendedFor; - } catch (error) { - return resolve({ - success : false, - message : error.message, - status : - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - data : { - description : CONSTANTS.common.PROJECT_DESCRIPTION, - data : [], - count : 0 - } - }); + if (UTILS.revertStatusorNot(appVersion)) { + projectDocument.status = UTILS.revertProjectStatus( + projectDocument.status + ); + } + let response = await reportService.projectAndTaskReport( + userToken, + projectDocument, + projectPdf + ); + + if (response && response.success == true) { + return resolve({ + success: true, + message: CONSTANTS.apiResponses.REPORT_GENERATED_SUCCESSFULLY, + data: { + data: { + downloadUrl: response.data.pdfUrl, + }, + }, + }); + } else { + throw { + message: CONSTANTS.apiResponses.COULD_NOT_GENERATE_PDF_REPORT, + }; } - }) + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: {}, + }); + } + }); } /** - * List of user imported projects. - * @method - * @name importedProjects - * @param {String} userId - Logged in user id. - * @param {String} programId - program id. - * @returns {Object} + * Get list of user projects with the targetted ones. + * @method + * @name userAssigned + * @param {String} userId - Logged in user id. + * @param {Number} pageSize - Page size. + * @param {Number} pageNo - Page No. + * @param {String} search - Search text. + * @param {String} filter - filter text. + * @returns {Object} */ - static importedProjects( userId,programId ) { + static userAssigned(userId, pageSize, pageNo, search, filter) { return new Promise(async (resolve, reject) => { - try { + try { + let query = { + userId: userId, + isDeleted: false, + }; + + let searchQuery = []; + + if (search !== "") { + searchQuery = [ + { title: new RegExp(search, "i") }, + { description: new RegExp(search, "i") }, + ]; + } - let filterQuery = { - userId : userId, - // referenceFrom : { $exists : true,$eq : CONSTANTS.common.OBSERVATION_REFERENCE_KEY }, - Commented as this filter is not useful. - 4.7 Sprint - 25Feb2022 - isDeleted: false + if (filter && filter !== "") { + if (filter === CONSTANTS.common.CREATED_BY_ME) { + query["referenceFrom"] = { + $ne: CONSTANTS.common.LINK, }; + query["isAPrivateProgram"] = { + $ne: false, + }; + } else if (filter == CONSTANTS.common.ASSIGN_TO_ME) { + query["isAPrivateProgram"] = false; + } else { + query["referenceFrom"] = CONSTANTS.common.LINK; + } + } - if( programId !== "" ) { - filterQuery["programId"] = programId; - } + let projects = await this.projects( + query, + pageSize, + pageNo, + searchQuery, + [ + "title", + "description", + "solutionId", + "programId", + "programInformation.name", + "projectTemplateId", + "solutionExternalId", + "lastDownloadedAt", + "hasAcceptedTAndC", + "referenceFrom", + "status", + "certificate", + ] + ); + + let totalCount = 0; + let data = []; + if ( + projects.success && + projects.data && + projects.data.data && + Object.keys(projects.data.data).length > 0 + ) { + totalCount = projects.data.count; + data = projects.data.data; + + if (data.length > 0) { + let templateFilePath = []; + data.forEach((projectData) => { + projectData.name = projectData.title; + + if (projectData.programInformation) { + projectData.programName = projectData.programInformation.name; + delete projectData.programInformation; + } + + if (projectData.solutionExternalId) { + projectData.externalId = projectData.solutionExternalId; + delete projectData.solutionExternalId; + } + + projectData.type = CONSTANTS.common.IMPROVEMENT_PROJECT; + delete projectData.title; + + if ( + projectData.certificate && + projectData.certificate.osid && + projectData.certificate.osid !== "" && + projectData.certificate.templateUrl && + projectData.certificate.templateUrl !== "" + ) { + templateFilePath.push(projectData.certificate.templateUrl); + } + }); - let importedProjects = await projectQueries.projectDocument( - filterQuery, - [ - "solutionInformation", - "programInformation", - "title", - "description", - "projectTemplateId", - "certificate.templateId" - ] - ); - - return resolve({ - success : true, - message : CONSTANTS.apiResponses.IMPORTED_PROJECTS_FETCHED, - data : importedProjects - }); - - } catch (error) { - return resolve({ - success : false, - message : error.message, - status : - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - data : { - description : CONSTANTS.common.PROJECT_DESCRIPTION, - data : [], - count : 0 + if (templateFilePath.length > 0) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl({ + filePaths: templateFilePath, + }); + if (!certificateTemplateDownloadableUrl.success) { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND, + }; + } + // map downloadable templateUrl to corresponding project data + data.forEach((projectData) => { + if (projectData.certificate) { + var itemFromUrlArray = + certificateTemplateDownloadableUrl.data.find( + (item) => + item.filePath == projectData.certificate.templateUrl + ); + if (itemFromUrlArray) { + projectData.certificate.templateUrl = itemFromUrlArray.url; + } } - }); + }); + } + } } - }) + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.USER_ASSIGNED_PROJECT_FETCHED, + data: { + data: data, + count: totalCount, + }, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + data: { + description: CONSTANTS.common.PROJECT_DESCRIPTION, + data: [], + count: 0, + }, + }); + } + }); } /** - * List of projects. + * List of user imported projects. * @method - * @name list - * @returns {Array} List of projects. + * @name importedProjects + * @param {String} userId - Logged in user id. + * @param {String} programId - program id. + * @returns {Object} */ - - static list( bodyData ) { - return new Promise(async (resolve, reject) => { - try { - let projects = await projectQueries.projectDocument( - bodyData.query, - bodyData.projection, - bodyData.skipFields - ); - return resolve({ - success : true, - message : CONSTANTS.apiResponses.PROJECTS_FETCHED, - result : projects - }); - - } catch (error) { - return reject(error); + static importedProjects(userId, programId) { + return new Promise(async (resolve, reject) => { + try { + let filterQuery = { + userId: userId, + // referenceFrom : { $exists : true,$eq : CONSTANTS.common.OBSERVATION_REFERENCE_KEY }, - Commented as this filter is not useful. - 4.7 Sprint - 25Feb2022 + isDeleted: false, + }; + + if (programId !== "") { + filterQuery["programId"] = programId; } + + let importedProjects = await projectQueries.projectDocument( + filterQuery, + [ + "solutionInformation", + "programInformation", + "title", + "description", + "projectTemplateId", + "certificate.templateId", + ] + ); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.IMPORTED_PROJECTS_FETCHED, + data: importedProjects, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + data: { + description: CONSTANTS.common.PROJECT_DESCRIPTION, + data: [], + count: 0, + }, + }); + } }); } /** - * Create project from template. - * @method - * @name importFromLibrary - * @param {String} projectTemplateId - project template id. - * @param {Object} requestedData - body data. - * @param {String} userId - Logged in user id. - * @param {String} userToken - User token. - * @param {Boolean} isATargetedSolution - User targeted or not . - * @returns {Object} Project created information. - */ - - static importFromLibrary(projectTemplateId, requestedData, userToken, userId, isATargetedSolution = "" ) { - return new Promise(async (resolve, reject) => { - try { - - isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); - - let libraryProjects = - await libraryCategoriesHelper.projectDetails( - projectTemplateId, - "", - isATargetedSolution - ); - - if ( - libraryProjects.data && - !Object.keys(libraryProjects.data).length > 0 - ) { - throw { - message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, - status: HTTP_STATUS_CODE['bad_request'].status - }; - - } - - let taskReport = {}; - - if ( - libraryProjects.data.tasks && - libraryProjects.data.tasks.length > 0 - ) { - - libraryProjects.data.tasks = await _projectTask( - libraryProjects.data.tasks, - isATargetedSolution === false ? false : true - ); - - taskReport.total = libraryProjects.data.tasks.length; - - libraryProjects.data.tasks.forEach(task => { - if ( task.isDeleted == false ) { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - } else { - //reduce total count if task is deleted. - taskReport.total = taskReport.total - 1; - } - - }); - - libraryProjects.data["taskReport"] = taskReport; - } - - if (requestedData.entityId && requestedData.entityId !== "") { - - let entityInformation = - await _entitiesInformation([requestedData.entityId]); - - if (!entityInformation.success) { - return resolve(entityInformation); - } - - libraryProjects.data["entityInformation"] = entityInformation.data[0]; - libraryProjects.data.entityId = entityInformation.data[0]._id; - } - - if( requestedData.solutionId && requestedData.solutionId !== "" && isATargetedSolution === false ){ - let programAndSolutionInformation = {}; - // Check if solutionId passed is private or not, if private and data is present, create program and solution information. - let solutionDetails = await solutionsHelper.solutionDocuments({ - _id: requestedData.solutionId, - isAPrivateProgram: true - }, - [ - "_id", - "name", - "externalId", - "description", - "programId", - "programName", - "programDescription", - "programExternalId", - "isAPrivateProgram", - "projectTemplateId", - "entityType", - "certificateTemplateId", - "parentSolutionId" - ]); - // private solution exists - if ( solutionDetails.length > 0 && solutionDetails[0].parentSolutionId ) { - // This function will return programAndSolutionInformation - /** - * function privateProgramAndSolutionDetails - * Request: - * @param {solutionDetails} solution data - * @response Program and solution details - */ - programAndSolutionInformation = await this.getProgramAndSolutionDetails(solutionDetails[0]); - } else { - programAndSolutionInformation = - await this.createProgramAndSolution( - requestedData.programId, - requestedData.programName, - requestedData.entityId ? [requestedData.entityId] : "", - userToken, - requestedData.solutionId, - isATargetedSolution - ); - } - - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } - - libraryProjects.data = _.merge( - libraryProjects.data, - programAndSolutionInformation.data - ) - - libraryProjects.data["referenceFrom"] = CONSTANTS.common.LINK; - } - else if ( - (requestedData.programId && requestedData.programId !== "") || - (requestedData.programName && requestedData.programName !== "" ) - ) { - - let programAndSolutionInformation = - await this.createProgramAndSolution( - requestedData.programId, - requestedData.programName, - requestedData.entityId ? [requestedData.entityId] : "", - userToken - ); - - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } - - if ( - libraryProjects.data["entityInformation"] && - libraryProjects.data["entityInformation"].entityType !== - programAndSolutionInformation.data.solutionInformation.entityType - ) { - throw { - message: CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, - status: HTTP_STATUS_CODE['bad_request'].status - } - } - - libraryProjects.data = _.merge( - libraryProjects.data, - programAndSolutionInformation.data - ) - } - // <- Add certificate template data - if ( - libraryProjects.data.certificateTemplateId && - libraryProjects.data.certificateTemplateId !== "" - ){ - // <- Add certificate template details to projectCreation data if present -> - const certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : libraryProjects.data.certificateTemplateId - }); - - // create certificate object and add data if certificate template is present. - if ( certificateTemplateDetails.length > 0 ) { - libraryProjects.data["certificate"] = _.pick(certificateTemplateDetails[0], ['templateUrl', 'status', 'criteria']); - } - libraryProjects.data["certificate"]["templateId"] = libraryProjects.data.certificateTemplateId; - delete libraryProjects.data.certificateTemplateId; - } - - //Fetch user profile information by calling sunbird's user read api. - let addReportInfoToSolution = false; - let userProfile = await userProfileService.profile(userToken, userId); - if ( userProfile.success && - userProfile.data && - userProfile.data.response - ) { - libraryProjects.data.userProfile = userProfile.data.response; - addReportInfoToSolution = true; - } - - libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; - libraryProjects.data.lastDownloadedAt = new Date(); - libraryProjects.data.status = CONSTANTS.common.STARTED; - - if (requestedData.startDate) { - libraryProjects.data.startDate = requestedData.startDate; - } - - if (requestedData.endDate) { - libraryProjects.data.endDate = requestedData.endDate; - } - - if (requestedData.hasAcceptedTAndC) { - libraryProjects.data.hasAcceptedTAndC = true; - } - - libraryProjects.data.projectTemplateId = libraryProjects.data._id; - libraryProjects.data.projectTemplateExternalId = libraryProjects.data.externalId; - - let projectCreation = await database.models.projects.create( - _.omit(libraryProjects.data, ["_id"]) - ); - - if ( addReportInfoToSolution && projectCreation._doc.solutionId ) { - - let updateSolution = await solutionsHelper.addReportInformationInSolution( - projectCreation._doc.solutionId, - projectCreation._doc.userProfile - ); - } - - await kafkaProducersHelper.pushProjectToKafka(projectCreation); - - if (requestedData.rating && requestedData.rating > 0) { - await projectTemplatesHelper.ratings( - projectTemplateId, - requestedData.rating, - userToken - ); - } - - projectCreation = await _projectInformation(projectCreation._doc); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: projectCreation.data - }); - - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {} - }); - } - }) - } - - /** - * get project details. - * @method - * @name userProject - * @param {String} projectId - project id. - * @returns {Object} Project details. - */ - - static userProject(projectId) { - return new Promise(async (resolve, reject) => { - try { - - const projectDetails = await projectQueries.projectDocument({ - _id: projectId, - }, "all"); - - if (!projectDetails.length > 0) { - - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND - } - } - - return resolve( { - success: true, - message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, - data: projectDetails[0] - }); - - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {} - }); - } - }) - } - - /** - * generate project certificate. - * @method - * @name generateCertificate - * @param {Object} data - project data for certificate creation data. - * @returns {JSON} certificate details. - */ - - static generateCertificate(data) { - return new Promise(async (resolve, reject) => { - try { - - // check eligibility of project for certificate creation - let eligibility = await this.checkCertificateEligibility(data); - if (!eligibility ){ - throw { - message: CONSTANTS.apiResponses.NOT_ELIGIBLE_FOR_CERTIFICATE - }; - } - - // create payload for certificate generation - const certificateData = await this.createCertificatePayload(data); - - // call sunbird-RC to create certificate for project - const certificate = await this.createCertificate(certificateData, data._id) - - return resolve(certificate); - - } catch (error) { - return resolve({ - success: false, - message: error.message - - }); - } - }) - } - - /** - * check project eligibility for certificate. - * @method - * @name checkCertificateEligibility - * @param {Object} data - project data for certificate creation data. - * @returns {Boolean} certificate eligibilty status. - */ - - static checkCertificateEligibility(data) { - return new Promise(async (resolve, reject) => { - try { - let eligible = false; - let updateObject = { - "$set" : {} - }; - // validate certificate data, checking if it passes all criteria - let validateCriteria = await certificateValidationsHelper.criteriaValidation(data) - if ( validateCriteria.success ) { - eligible = true; - } else { - updateObject["$set"]["certificate.message"] = validateCriteria.message; - } - updateObject["$set"]["certificate.eligible"] = eligible; - - // update project certificate data - await projectQueries.findOneAndUpdate( - { - _id: data._id - }, - updateObject - ); - - return resolve(eligible); - } catch (error) { - return resolve({ - success: false, - message: error.message - - }); - } - }) - } - - /** - * createCertificatePayload. - * @method - * @name createCertificatePayload - * @param {Object} data - project data for certificate creation data. - * @returns {Object} payload for certificate creation. - */ - - static createCertificatePayload(data) { - return new Promise(async (resolve, reject) => { - try { - console.log("Certificate issuer Kid: ",CERTIFICATE_ISSUER_KID) - - if(data.title.length > 75) { - data.title = data.title.substring(0, 75) + '...'; - } - - // get downloadable url for certificate template - if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: [data.certificate.templateUrl] - } - ); - if ( certificateTemplateDownloadableUrl.success ) { - data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; - } else { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND - }; - } - } - - let certificateTemplateDetails =[]; - if ( data.certificate.templateId && data.certificate.templateId !== "" ) { - certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ - _id : data.certificate.templateId - },["issuer","solutionId","programId"]); - - //certificate template data do not exists. - if ( !certificateTemplateDetails.length > 0 ) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND - }; - } - certificateTemplateDetails[0].issuer.kid = CERTIFICATE_ISSUER_KID; - } - - //create certificate request body - let certificateData = { - recipient : { - id : data.userId, - name : `${data.userProfile.firstName} ${data.userProfile.lastName}`, - type : data.userProfile.profileUserType.type - }, - templateUrl : data.certificate.templateUrl, - issuer : certificateTemplateDetails[0].issuer, - status : data.certificate.status.toUpperCase(), - projectId : (data._id).toString(), - projectName : data.title, - programId : (certificateTemplateDetails[0].programId).toString(), - programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", - solutionId : (certificateTemplateDetails[0].solutionId).toString(), - solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", - completedDate : data.completedDate - }; - return resolve(certificateData); - - } catch (error) { - console.log("error:",error.message) - return resolve({ - success: false, - message: error.message - - }); - } - }) - } - - /** - * call sunbird-RC for certificate creation. - * @method - * @name createCertificate - * @param {Object} certificateData - payload for certificate creation data. - * @param {string} projectId - project Id. - * @returns {Boolean} certificate creation status. - */ + * List of projects. + * @method + * @name list + * @returns {Array} List of projects. + */ - static createCertificate(certificateData, projectId) { - return new Promise(async (resolve, reject) => { - try { + static list(bodyData) { + return new Promise(async (resolve, reject) => { + try { + let projects = await projectQueries.projectDocument( + bodyData.query, + bodyData.projection, + bodyData.skipFields + ); - const certificateDetails = await certificateService.createCertificate( certificateData ); - - if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED - }; - } - - let updateObject = { - "$set" : {} - }; + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + result: projects, + }); + } catch (error) { + return reject(error); + } + }); + } - // if transaction id is present. - if ( certificateDetails.data.ProjectCertificate.transactionId && - certificateDetails.data.ProjectCertificate.transactionId !== "" - ) { - let transactionIdvalue = certificateDetails.data.ProjectCertificate.transactionId; - const first2 = transactionIdvalue.slice(0, 2); - - if ( first2 === "1-" ) { - transactionIdvalue = transactionIdvalue.split(/1-(.*)/s) - updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; - } else { - updateObject["$set"]["certificate.transactionId"] = transactionIdvalue; - } - - } + /** + * Create project from template. + * @method + * @name importFromLibrary + * @param {String} projectTemplateId - project template id. + * @param {Object} requestedData - body data. + * @param {String} userId - Logged in user id. + * @param {String} userToken - User token. + * @param {Boolean} isATargetedSolution - User targeted or not . + * @returns {Object} Project created information. + */ - // update project details certificate details - if ( certificateDetails.data.ProjectCertificate.osid && - certificateDetails.data.ProjectCertificate.osid !== "" - ) { - updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; - updateObject["$set"]["certificate.issuedOn"] = new Date(); - } - updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date();; - - if ( Object.keys(updateObject["$set"]).length > 0 ) { - let updatedProject = await projectQueries.findOneAndUpdate( - { - _id: projectId - }, - updateObject - ); - } - return resolve( { - success: true - }); - } catch (error) { - return resolve({ - success: false, - message: error.message + static importFromLibrary( + projectTemplateId, + requestedData, + userToken, + userId, + isATargetedSolution = "" + ) { + return new Promise(async (resolve, reject) => { + try { + isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); + + let libraryProjects = await libraryCategoriesHelper.projectDetails( + projectTemplateId, + "", + isATargetedSolution + ); + + if ( + libraryProjects.data && + !Object.keys(libraryProjects.data).length > 0 + ) { + throw { + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - }); + let taskReport = {}; + + if ( + libraryProjects.data.tasks && + libraryProjects.data.tasks.length > 0 + ) { + libraryProjects.data.tasks = await _projectTask( + libraryProjects.data.tasks, + isATargetedSolution === false ? false : true + ); + + taskReport.total = libraryProjects.data.tasks.length; + + libraryProjects.data.tasks.forEach((task) => { + if (task.isDeleted == false) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + } else { + //reduce total count if task is deleted. + taskReport.total = taskReport.total - 1; } - }) - } - - /** - * certificate callback - * @method - * @name certificateCallback - * @param {String} transactionId - transactionId for create certificate. - * @param {String} osid - osid for created certificate. - * @returns {JSON} certificate data updation details. - */ + }); - static certificateCallback(transactionId, osid) { - return new Promise(async (resolve, reject) => { - try { - // adding comments to check call back is called properly or not - console.log("<==================callback called====================>",transactionId,osid) - console.log("transactionId :",transactionId) - console.log("osid :",osid) - console.log("<==================callback called====================>") - // callback request structure nested so validating transactionId and osid here instead in validator. - if ( transactionId == "" || osid == "" ) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.TRANSACTION_ID_AND_OSID_REQUIRED - } - } - let updateObject = { - "$set" : {} - }; - - // update osid and eligibility based on transactionId - updateObject["$set"]["certificate.osid"] = osid; - updateObject["$set"]["certificate.message"] = CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY; - updateObject["$set"]["certificate.issuedOn"] = new Date(); - - let projectDetails = await projectQueries.findOneAndUpdate( - { - "certificate.transactionId" : transactionId - }, - updateObject - ); - - if ( projectDetails == null || !Object.keys(projectDetails).length > 0 ) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND - } - } - await kafkaProducersHelper.pushProjectToKafka(projectDetails); - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, - data : { - _id : ObjectId(projectDetails._id) - } - - }); + libraryProjects.data["taskReport"] = taskReport; + } - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {} - }); - } - }) - } + if (requestedData.entityId && requestedData.entityId !== "") { + let entityInformation = await _entitiesInformation([ + requestedData.entityId, + ]); - /** - * List user project details with certificate - * @method - * @name certificates - * @param {String} userId - userId. - * @returns {JSON} certificate data updation details. - */ + if (!entityInformation.success) { + return resolve(entityInformation); + } - static certificates(userId) { - return new Promise(async (resolve, reject) => { - try { - - // get project details of user which have certificate. - const userProject = await projectQueries.projectDocument({ - userId: userId, - status: CONSTANTS.common.SUBMITTED_STATUS, - certificate: {$exists:true} - }, [ - "_id", - "title", - "status", - "certificate.osid", - "certificate.transactioId", - "certificate.templateUrl", - "certificate.status", - "certificate.eligible", - "certificate.message", - "certificate.issuedOn", - "completedDate" - ]); - - if ( !userProject.length > 0 ) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND - } - } - let templateFilePath = []; - //loop through user projects and get downloadable url for templateUrl if osid is present. - for( let userProjectPointer = 0; userProjectPointer < userProject.length; userProjectPointer++ ) { - if ( userProject[userProjectPointer].certificate.osid && - userProject[userProjectPointer].certificate.osid !== "" && - userProject[userProjectPointer].certificate.templateUrl && - userProject[userProjectPointer].certificate.templateUrl !== "" - ) { - templateFilePath.push(userProject[userProjectPointer].certificate.templateUrl); - } - } - - if( templateFilePath.length > 0 ) { - - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl( - { - filePaths: templateFilePath - } - ); - if ( !certificateTemplateDownloadableUrl.success ) { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND - }; - } - // map downloadable templateUrl to corresponding project data - userProject.forEach(projectData => { - var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find(item=> item.filePath == projectData.certificate.templateUrl); - if (itemFromUrlArray) { - projectData.certificate.templateUrl = itemFromUrlArray.url; - } - } - ) - } + libraryProjects.data["entityInformation"] = entityInformation.data[0]; + libraryProjects.data.entityId = entityInformation.data[0]._id; + } - let count = _.countBy(userProject, (rec) => { - return (rec.certificate && rec.certificate.osid && rec.certificate.osid !== "" )? 'generated': 'notGenerated'; - }); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data : { - data : userProject, - count : userProject.length, - certificateCount : count.generated - } + if ( + requestedData.solutionId && + requestedData.solutionId !== "" && + isATargetedSolution === false + ) { + let programAndSolutionInformation = {}; + // Check if solutionId passed is private or not, if private and data is present, create program and solution information. + let solutionDetails = await solutionsHelper.solutionDocuments( + { + _id: requestedData.solutionId, + isAPrivateProgram: true, + }, + [ + "_id", + "name", + "externalId", + "description", + "programId", + "programName", + "programDescription", + "programExternalId", + "isAPrivateProgram", + "projectTemplateId", + "entityType", + "certificateTemplateId", + "parentSolutionId", + ] + ); + // private solution exists + if ( + solutionDetails.length > 0 && + solutionDetails[0].parentSolutionId + ) { + // This function will return programAndSolutionInformation + /** + * function privateProgramAndSolutionDetails + * Request: + * @param {solutionDetails} solution data + * @response Program and solution details + */ + programAndSolutionInformation = + await this.getProgramAndSolutionDetails(solutionDetails[0]); + } else { + programAndSolutionInformation = await this.createProgramAndSolution( + requestedData.programId, + requestedData.programName, + requestedData.entityId ? [requestedData.entityId] : "", + userToken, + requestedData.solutionId, + isATargetedSolution + ); + } + + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + + libraryProjects.data = _.merge( + libraryProjects.data, + programAndSolutionInformation.data + ); + + libraryProjects.data["referenceFrom"] = CONSTANTS.common.LINK; + } else if ( + (requestedData.programId && requestedData.programId !== "") || + (requestedData.programName && requestedData.programName !== "") + ) { + let programAndSolutionInformation = + await this.createProgramAndSolution( + requestedData.programId, + requestedData.programName, + requestedData.entityId ? [requestedData.entityId] : "", + userToken + ); - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {} - }); - } - }) - } + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + + if ( + libraryProjects.data["entityInformation"] && + libraryProjects.data["entityInformation"].entityType !== + programAndSolutionInformation.data.solutionInformation.entityType + ) { + throw { + message: CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, + status: HTTP_STATUS_CODE["bad_request"].status, + }; + } - /** - * Re-Issue project certificate - * @method - * @name certificateReIssue - * @param {String} projectId - projectId. - * @returns {JSON} certificate re-issued details. - */ + libraryProjects.data = _.merge( + libraryProjects.data, + programAndSolutionInformation.data + ); + } + // <- Add certificate template data + if ( + libraryProjects.data.certificateTemplateId && + libraryProjects.data.certificateTemplateId !== "" + ) { + // <- Add certificate template details to projectCreation data if present -> + const certificateTemplateDetails = + await certificateTemplateQueries.certificateTemplateDocument({ + _id: libraryProjects.data.certificateTemplateId, + }); - static certificateReIssue(projectId) { - return new Promise(async (resolve, reject) => { - try { - // get project details project for which certificate re-issue required . - const userProject = await projectQueries.projectDocument({ - _id: projectId, - status: CONSTANTS.common.SUBMITTED_STATUS, - certificate: {$exists:true} - }); + // create certificate object and add data if certificate template is present. + if (certificateTemplateDetails.length > 0) { + libraryProjects.data["certificate"] = _.pick( + certificateTemplateDetails[0], + ["templateUrl", "status", "criteria"] + ); + } + libraryProjects.data["certificate"]["templateId"] = + libraryProjects.data.certificateTemplateId; + delete libraryProjects.data.certificateTemplateId; + } - // if project details not found. - if (!userProject.length > 0) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND - }; - } - let updateObject = { - "$set" : {} - }; - - // fetch user data using userId of project and calling the profile API - let userProfileData = await userProfileService.profileReadPrivate(userProject[0].userId); - if ( userProfileData.success && - userProfileData.data && - userProfileData.data.response && - userProfileData.data.response.firstName && - userProfileData.data.response.firstName !== "" - ) { - userProject[0].userProfile.firstName = userProfileData.data.response.firstName; - userProject[0].userProfile.lastName = userProfileData.data.response.lastName; - } else { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND - }; - } + //Fetch user profile information by calling sunbird's user read api. + let addReportInfoToSolution = false; + let userProfile = await userProfileService.profile(userToken, userId); + if ( + userProfile.success && + userProfile.data && + userProfile.data.response + ) { + libraryProjects.data.userProfile = userProfile.data.response; + addReportInfoToSolution = true; + } - // create payload for certificate generation - const certificateData = await this.createCertificatePayload(userProject[0]); + libraryProjects.data.userId = + libraryProjects.data.updatedBy = + libraryProjects.data.createdBy = + userId; + libraryProjects.data.lastDownloadedAt = new Date(); + libraryProjects.data.status = CONSTANTS.common.STARTED; - // call sunbird-RC to create certificate for project - const certificate = await this.createCertificate(certificateData, userProject[0]._id); + if (requestedData.startDate) { + libraryProjects.data.startDate = requestedData.startDate; + } - if ( !certificate.success ) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED - }; - } + if (requestedData.endDate) { + libraryProjects.data.endDate = requestedData.endDate; + } - if ( userProject[0].certificate.transactionId ) { - updateObject["$set"]["certificate.originalTransactionInformation.transactionId"] = userProject[0].certificate.transactionId - } - if ( userProject[0].certificate.osid ) { - updateObject["$set"]["certificate.originalTransactionInformation.osid"] = userProject[0].certificate.osid; - } + if (requestedData.hasAcceptedTAndC) { + libraryProjects.data.hasAcceptedTAndC = true; + } - if (userProject[0].userProfile.firstName ) { - updateObject["$set"]["userProfile.firstName"] = userProject[0].userProfile.firstName; - } + libraryProjects.data.projectTemplateId = libraryProjects.data._id; + libraryProjects.data.projectTemplateExternalId = + libraryProjects.data.externalId; - if (userProject[0].userProfile.lastName ) { - updateObject["$set"]["userProfile.lastName"] = userProject[0].userProfile.lastName; - } + let projectCreation = await database.models.projects.create( + _.omit(libraryProjects.data, ["_id"]) + ); - updateObject["$set"]["certificate.reIssuedAt"] = new Date(); - await projectQueries.findOneAndUpdate( - { - _id: userProject[0]._id - }, - updateObject - ); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_SUBMITTED_FOR_REISSUE, - data : { - _id : userProject[0]._id - } + if (addReportInfoToSolution && projectCreation._doc.solutionId) { + let updateSolution = + await solutionsHelper.addReportInformationInSolution( + projectCreation._doc.solutionId, + projectCreation._doc.userProfile + ); + } - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {} - }); - } - }) - } + await kafkaProducersHelper.pushProjectToKafka(projectCreation); + if (requestedData.rating && requestedData.rating > 0) { + await projectTemplatesHelper.ratings( + projectTemplateId, + requestedData.rating, + userToken + ); + } -}; + projectCreation = await _projectInformation(projectCreation._doc); -/** - * Project information. - * @method - * @name _projectInformation - * @param {Object} project - Project data. - * @returns {Object} Project information. -*/ + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data: projectCreation.data, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {}, + }); + } + }); + } -function _projectInformation(project) { + /** + * get project details. + * @method + * @name userProject + * @param {String} projectId - project id. + * @returns {Object} Project details. + */ + static userProject(projectId) { return new Promise(async (resolve, reject) => { - try { - - if (project.entityInformation) { - project.entityId = project.entityInformation._id; - project.entityName = project.entityInformation.name; - } + try { + const projectDetails = await projectQueries.projectDocument( + { + _id: projectId, + }, + "all" + ); + + if (!projectDetails.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, + }; + } - if (project.programInformation) { - project.programId = project.programInformation._id; - project.programName = project.programInformation.name; - } - - //project attachments - if ( project.attachments && project.attachments.length > 0 ) { - - let projectLinkAttachments = []; - let projectAttachments = []; - - for ( - let pointerToAttachment = 0; - pointerToAttachment < project.attachments.length; - pointerToAttachment++ - ) { + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, + data: projectDetails[0], + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {}, + }); + } + }); + } - let currentProjectAttachment = project.attachments[pointerToAttachment]; - if ( currentProjectAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { - projectLinkAttachments.push(currentProjectAttachment); - } else { - projectAttachments.push(currentProjectAttachment.sourcePath); - } - } - - let projectAttachmentsUrl = await _attachmentInformation(projectAttachments, projectLinkAttachments, project.attachments, CONSTANTS.common.PROJECT_ATTACHMENT); - if ( projectAttachmentsUrl.data && projectAttachmentsUrl.data.length > 0 ) { - project.attachments = projectAttachmentsUrl.data; - } - - } - - //task attachments - if (project.tasks && project.tasks.length > 0) { - //order task based on task sequence - if ( project.taskSequence && project.taskSequence.length > 0 ) { - project.tasks = taskArrayBySequence(project.tasks, project.taskSequence, 'externalId'); - } + /** + * generate project certificate. + * @method + * @name generateCertificate + * @param {Object} data - project data for certificate creation data. + * @returns {JSON} certificate details. + */ - let attachments = []; - let mapTaskIdToAttachment = {}; - let mapLinkAttachment = {}; - - for (let task = 0; task < project.tasks.length; task++) { - - let currentTask = project.tasks[task]; - - if (currentTask.attachments && currentTask.attachments.length > 0) { - for ( - let attachment = 0; - attachment < currentTask.attachments.length; - attachment++ - ) { - let currentAttachment = currentTask.attachments[attachment]; - - if (currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { - if (!Array.isArray(mapLinkAttachment[currentTask._id]) || !mapLinkAttachment[currentTask._id].length ) { - mapLinkAttachment[currentTask._id] = []; - } - mapLinkAttachment[currentTask._id].push(currentAttachment); - } else { - attachments.push(currentAttachment.sourcePath); - } - - if (!mapTaskIdToAttachment[currentAttachment.sourcePath] && currentAttachment.type != CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { - mapTaskIdToAttachment[currentAttachment.sourcePath] = { - taskId: currentTask._id - }; - } - } - } - } + static generateCertificate(data) { + return new Promise(async (resolve, reject) => { + try { + // check eligibility of project for certificate creation + let eligibility = await this.checkCertificateEligibility(data); + if (!eligibility) { + throw { + message: CONSTANTS.apiResponses.NOT_ELIGIBLE_FOR_CERTIFICATE, + }; + } - let taskAttachmentsUrl = await _attachmentInformation(attachments, mapLinkAttachment, [], CONSTANTS.common.TASK_ATTACHMENT, mapTaskIdToAttachment, project.tasks); - if ( taskAttachmentsUrl.data && taskAttachmentsUrl.data.length > 0 ) { - project.tasks = taskAttachmentsUrl.data; - } - } - - project.status = - project.status ? project.status : CONSTANTS.common.NOT_STARTED_STATUS; + // create payload for certificate generation + const certificateData = await this.createCertificatePayload(data); - if (project.metaInformation) { - Object.keys(project.metaInformation).forEach(projectMetaKey => { - project[projectMetaKey] = project.metaInformation[projectMetaKey]; - }); - } + // call sunbird-RC to create certificate for project + const certificate = await this.createCertificate( + certificateData, + data._id + ); - delete project.metaInformation; - delete project.__v; - delete project.entityInformation; - delete project.solutionInformation; - delete project.programInformation; + return resolve(certificate); + } catch (error) { + return resolve({ + success: false, + message: error.message, + }); + } + }); + } - return resolve({ - success: true, - data: project - }); + /** + * check project eligibility for certificate. + * @method + * @name checkCertificateEligibility + * @param {Object} data - project data for certificate creation data. + * @returns {Boolean} certificate eligibilty status. + */ - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }) + static checkCertificateEligibility(data) { + return new Promise(async (resolve, reject) => { + try { + let eligible = false; + let updateObject = { + $set: {}, + }; + // validate certificate data, checking if it passes all criteria + let validateCriteria = + await certificateValidationsHelper.criteriaValidation(data); + if (validateCriteria.success) { + eligible = true; + } else { + updateObject["$set"]["certificate.message"] = + validateCriteria.message; } - }) -} + updateObject["$set"]["certificate.eligible"] = eligible; + + // update project certificate data + await projectQueries.findOneAndUpdate( + { + _id: data._id, + }, + updateObject + ); + + return resolve(eligible); + } catch (error) { + return resolve({ + success: false, + message: error.message, + }); + } + }); + } -function taskArrayBySequence (taskArray, sequenceArray, key) { - var map = sequenceArray.reduce((acc, value, index) => (acc[value] = index + 1, acc), {}) - const sortedTaskArray = taskArray.sort((a, b) => (map[a[key]] || Infinity) - (map[b[key]] || Infinity)) - return sortedTaskArray -}; + /** + * createCertificatePayload. + * @method + * @name createCertificatePayload + * @param {Object} data - project data for certificate creation data. + * @returns {Object} payload for certificate creation. + */ -/** - * Attachment information of project. - * @method - * @name _attachmentInformation - * @param {Array} attachments - attachments data. - * @param {String} type - project or task attachement. - * @returns {Object} Project attachments. -*/ -function _attachmentInformation ( attachmentWithSourcePath = [], linkAttachments = [], attachments = [] , type, mapTaskIdToAttachment = {}, tasks = []) { + static createCertificatePayload(data) { return new Promise(async (resolve, reject) => { - try { - - let attachmentOrTask = []; - - if ( attachmentWithSourcePath && attachmentWithSourcePath.length > 0 ) { - - let attachmentsUrl = - await coreService.getDownloadableUrl( - { - filePaths: attachmentWithSourcePath - } - ); - - if (!attachmentsUrl.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND - } - } + try { + console.log("Certificate issuer Kid: ", CERTIFICATE_ISSUER_KID); - if ( attachmentsUrl.data && attachmentsUrl.data.length > 0) { - - if (type === CONSTANTS.common.PROJECT_ATTACHMENT ) { + if (data.title.length > 75) { + data.title = data.title.substring(0, 75) + "..."; + } - attachmentsUrl.data.forEach(eachAttachment => { - - let projectAttachmentIndex = - attachments.findIndex(attachmentData => attachmentData.sourcePath == eachAttachment.filePath); - - if (projectAttachmentIndex > -1) { - attachments[projectAttachmentIndex].url = eachAttachment.url; - } - }) + // get downloadable url for certificate template + if ( + data.certificate.templateUrl && + data.certificate.templateUrl !== "" + ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl({ + filePaths: [data.certificate.templateUrl], + }); + if (certificateTemplateDownloadableUrl.success) { + data.certificate.templateUrl = + certificateTemplateDownloadableUrl.data[0].url; + } else { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND, + }; + } + } - } else { + let certificateTemplateDetails = []; + if (data.certificate.templateId && data.certificate.templateId !== "") { + certificateTemplateDetails = + await certificateTemplateQueries.certificateTemplateDocument( + { + _id: data.certificate.templateId, + }, + ["issuer", "solutionId", "programId"] + ); - attachmentsUrl.data.forEach(taskAttachments => { + //certificate template data do not exists. + if (!certificateTemplateDetails.length > 0) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND, + }; + } + certificateTemplateDetails[0].issuer.kid = CERTIFICATE_ISSUER_KID; + } - let taskIndex = - tasks.findIndex(task => task._id === mapTaskIdToAttachment[taskAttachments.filePath].taskId); + //create certificate request body + let certificateData = { + recipient: { + id: data.userId, + name: `${data.userProfile.firstName} ${data.userProfile.lastName}`, + type: data.userProfile.profileUserType.type, + }, + templateUrl: data.certificate.templateUrl, + issuer: certificateTemplateDetails[0].issuer, + status: data.certificate.status.toUpperCase(), + projectId: data._id.toString(), + projectName: data.title, + programId: certificateTemplateDetails[0].programId.toString(), + programName: + data.programInformation && data.programInformation.name + ? data.programInformation.name + : "", + solutionId: certificateTemplateDetails[0].solutionId.toString(), + solutionName: + data.solutionInformation && data.solutionInformation.name + ? data.solutionInformation.name + : "", + completedDate: data.completedDate, + }; + return resolve(certificateData); + } catch (error) { + console.log("error:", error.message); + return resolve({ + success: false, + message: error.message, + }); + } + }); + } - if (taskIndex > -1) { - - let attachmentIndex = - tasks[taskIndex].attachments.findIndex(attachment => attachment.sourcePath === taskAttachments.filePath); + /** + * call sunbird-RC for certificate creation. + * @method + * @name createCertificate + * @param {Object} certificateData - payload for certificate creation data. + * @param {string} projectId - project Id. + * @returns {Boolean} certificate creation status. + */ - if (attachmentIndex > -1) { - tasks[taskIndex].attachments[attachmentIndex].url = taskAttachments.url; - } - } - }) - } - } - } + static createCertificate(certificateData, projectId) { + return new Promise(async (resolve, reject) => { + try { + const certificateDetails = await certificateService.createCertificate( + certificateData + ); + + if ( + !certificateDetails.success || + !certificateDetails.data || + !certificateDetails.data.ProjectCertificate + ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED, + }; + } - if ( linkAttachments && linkAttachments.length > 0 ) { + let updateObject = { + $set: {}, + }; + + // if transaction id is present. + if ( + certificateDetails.data.ProjectCertificate.transactionId && + certificateDetails.data.ProjectCertificate.transactionId !== "" + ) { + let transactionIdvalue = + certificateDetails.data.ProjectCertificate.transactionId; + const first2 = transactionIdvalue.slice(0, 2); + + if (first2 === "1-") { + transactionIdvalue = transactionIdvalue.split(/1-(.*)/s); + updateObject["$set"]["certificate.transactionId"] = + transactionIdvalue[1]; + } else { + updateObject["$set"]["certificate.transactionId"] = + transactionIdvalue; + } + } - if (type === CONSTANTS.common.PROJECT_ATTACHMENT ) { - attachments.concat(linkAttachments); - + // update project details certificate details + if ( + certificateDetails.data.ProjectCertificate.osid && + certificateDetails.data.ProjectCertificate.osid !== "" + ) { + updateObject["$set"]["certificate.osid"] = + certificateDetails.data.ProjectCertificate.osid; + updateObject["$set"]["certificate.issuedOn"] = new Date(); + } + updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date(); - } else { + if (Object.keys(updateObject["$set"]).length > 0) { + let updatedProject = await projectQueries.findOneAndUpdate( + { + _id: projectId, + }, + updateObject + ); + } + return resolve({ + success: true, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + }); + } + }); + } - Object.keys(linkAttachments).forEach(eachTaskId => { + /** + * certificate callback + * @method + * @name certificateCallback + * @param {String} transactionId - transactionId for create certificate. + * @param {String} osid - osid for created certificate. + * @returns {JSON} certificate data updation details. + */ - let taskIdIndex = tasks.findIndex(task => task._id === eachTaskId); - if ( taskIdIndex > -1 ) { - tasks[taskIdIndex].attachments.concat(linkAttachments[eachTaskId]); - } - }) + static certificateCallback(transactionId, osid) { + return new Promise(async (resolve, reject) => { + try { + // adding comments to check call back is called properly or not + console.log( + "<==================callback called====================>", + transactionId, + osid + ); + console.log("transactionId :", transactionId); + console.log("osid :", osid); + console.log("<==================callback called====================>"); + // callback request structure nested so validating transactionId and osid here instead in validator. + if (transactionId == "" || osid == "") { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.TRANSACTION_ID_AND_OSID_REQUIRED, + }; + } + let updateObject = { + $set: {}, + }; + + // update osid and eligibility based on transactionId + updateObject["$set"]["certificate.osid"] = osid; + updateObject["$set"]["certificate.message"] = + CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY; + updateObject["$set"]["certificate.issuedOn"] = new Date(); + + let projectDetails = await projectQueries.findOneAndUpdate( + { + "certificate.transactionId": transactionId, + }, + updateObject + ); + + if (projectDetails == null || !Object.keys(projectDetails).length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, + }; + } + await kafkaProducersHelper.pushProjectToKafka(projectDetails); + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, + data: { + _id: ObjectId(projectDetails._id), + }, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {}, + }); + } + }); + } - } - } + /** + * List user project details with certificate + * @method + * @name certificates + * @param {String} userId - userId. + * @returns {JSON} certificate data updation details. + */ - attachmentOrTask = (type === CONSTANTS.common.PROJECT_ATTACHMENT) ? attachments : tasks + static certificates(userId) { + return new Promise(async (resolve, reject) => { + try { + // get project details of user which have certificate. + const userProject = await projectQueries.projectDocument( + { + userId: userId, + status: CONSTANTS.common.SUBMITTED_STATUS, + certificate: { $exists: true }, + }, + [ + "_id", + "title", + "status", + "certificate.osid", + "certificate.transactioId", + "certificate.templateUrl", + "certificate.status", + "certificate.eligible", + "certificate.message", + "certificate.issuedOn", + "completedDate", + ] + ); + + if (!userProject.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND, + }; + } + let templateFilePath = []; + //loop through user projects and get downloadable url for templateUrl if osid is present. + for ( + let userProjectPointer = 0; + userProjectPointer < userProject.length; + userProjectPointer++ + ) { + if ( + userProject[userProjectPointer].certificate.osid && + userProject[userProjectPointer].certificate.osid !== "" && + userProject[userProjectPointer].certificate.templateUrl && + userProject[userProjectPointer].certificate.templateUrl !== "" + ) { + templateFilePath.push( + userProject[userProjectPointer].certificate.templateUrl + ); + } + } - return resolve({ - success: true, - data: attachmentOrTask + if (templateFilePath.length > 0) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl({ + filePaths: templateFilePath, }); + if (!certificateTemplateDownloadableUrl.success) { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND, + }; + } + // map downloadable templateUrl to corresponding project data + userProject.forEach((projectData) => { + var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find( + (item) => item.filePath == projectData.certificate.templateUrl + ); + if (itemFromUrlArray) { + projectData.certificate.templateUrl = itemFromUrlArray.url; + } + }); + } - } catch (error) { + let count = _.countBy(userProject, (rec) => { + return rec.certificate && + rec.certificate.osid && + rec.certificate.osid !== "" + ? "generated" + : "notGenerated"; + }); return resolve({ - message: error.message, - success: false, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }) - } + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data: { + data: userProject, + count: userProject.length, + certificateCount: count.generated, + }, + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {}, + }); + } + }); + } - }) -} + /** + * Re-Issue project certificate + * @method + * @name certificateReIssue + * @param {String} projectId - projectId. + * @returns {JSON} certificate re-issued details. + */ -/** - * Task of project. - * @method - * @name _projectTask - * @param {Array} tasks - tasks data. - * @param {String} userId - logged in user id. - * @returns {Object} Project task. -*/ + static certificateReIssue(projectId) { + return new Promise(async (resolve, reject) => { + try { + // get project details project for which certificate re-issue required . + const userProject = await projectQueries.projectDocument({ + _id: projectId, + status: CONSTANTS.common.SUBMITTED_STATUS, + certificate: { $exists: true }, + }); -function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { + // if project details not found. + if (!userProject.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND, + }; + } + let updateObject = { + $set: {}, + }; + + // fetch user data using userId of project and calling the profile API + let userProfileData = await userProfileService.profileReadPrivate( + userProject[0].userId + ); + if ( + userProfileData.success && + userProfileData.data && + userProfileData.data.response && + userProfileData.data.response.firstName && + userProfileData.data.response.firstName !== "" + ) { + userProject[0].userProfile.firstName = + userProfileData.data.response.firstName; + userProject[0].userProfile.lastName = + userProfileData.data.response.lastName; + } else { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND, + }; + } - tasks.forEach(singleTask => { - - singleTask.externalId = singleTask.externalId ? singleTask.externalId : singleTask.name.toLowerCase(); - singleTask.type = singleTask.type ? singleTask.type : CONSTANTS.common.SIMPLE_TASK_TYPE; - singleTask.status = singleTask.status ? singleTask.status : CONSTANTS.common.NOT_STARTED_STATUS; - singleTask.isDeleted = singleTask.isDeleted ? singleTask.isDeleted : false; + // create payload for certificate generation + const certificateData = await this.createCertificatePayload( + userProject[0] + ); + + // call sunbird-RC to create certificate for project + const certificate = await this.createCertificate( + certificateData, + userProject[0]._id + ); + + if (!certificate.success) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED, + }; + } - if (!singleTask.hasOwnProperty("isDeletable")) { - singleTask.isDeletable = true; + if (userProject[0].certificate.transactionId) { + updateObject["$set"][ + "certificate.originalTransactionInformation.transactionId" + ] = userProject[0].certificate.transactionId; } - if ( UTILS.isValidMongoId(singleTask._id.toString()) ) { - singleTask.referenceId = singleTask._id.toString(); + if (userProject[0].certificate.osid) { + updateObject["$set"][ + "certificate.originalTransactionInformation.osid" + ] = userProject[0].certificate.osid; } - singleTask.createdAt = singleTask.createdAt ? singleTask.createdAt : new Date(); - singleTask.updatedAt = new Date(); - singleTask._id = UTILS.isValidMongoId(singleTask._id.toString()) ? uuidv4() : singleTask._id; - singleTask.isImportedFromLibrary = isImportedFromLibrary; - singleTask.syncedAt = new Date(); - if (singleTask.startDate) { - singleTask.startDate = singleTask.startDate; + if (userProject[0].userProfile.firstName) { + updateObject["$set"]["userProfile.firstName"] = + userProject[0].userProfile.firstName; } - if (singleTask.endDate) { - singleTask.endDate = singleTask.endDate; + if (userProject[0].userProfile.lastName) { + updateObject["$set"]["userProfile.lastName"] = + userProject[0].userProfile.lastName; } - if (singleTask.visibleIf && singleTask.visibleIf.length > 0) { + updateObject["$set"]["certificate.reIssuedAt"] = new Date(); + await projectQueries.findOneAndUpdate( + { + _id: userProject[0]._id, + }, + updateObject + ); - if (parentTaskId !== "") { - singleTask.visibleIf.forEach(task => { - task._id = parentTaskId; - }); - } - } - - removeFieldsFromRequest.forEach((removeField) => { - delete singleTask[removeField]; + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_SUBMITTED_FOR_REISSUE, + data: { + _id: userProject[0]._id, + }, }); - - if (singleTask.children) { - _projectTask( - singleTask.children, - isImportedFromLibrary, - singleTask._id - ); - } else { - singleTask.children = []; - } - - }) - - return tasks; -} + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {}, + }); + } + }); + } +}; /** - * Project categories information. - * @method - * @name _projectCategories - * @param {Array} categories - Categories data. - * @returns {Object} Project categories information. -*/ - -function _projectCategories(categories) { - return new Promise(async (resolve, reject) => { - try { + * Project information. + * @method + * @name _projectInformation + * @param {Object} project - Project data. + * @returns {Object} Project information. + */ - let categoryIds = []; +function _projectInformation(project) { + return new Promise(async (resolve, reject) => { + try { + if (project.entityInformation) { + project.entityId = project.entityInformation._id; + project.entityName = project.entityInformation.name; + } + + if (project.programInformation) { + project.programId = project.programInformation._id; + project.programName = project.programInformation.name; + } + + //project attachments + if (project.attachments && project.attachments.length > 0) { + let projectLinkAttachments = []; + let projectAttachments = []; + + for ( + let pointerToAttachment = 0; + pointerToAttachment < project.attachments.length; + pointerToAttachment++ + ) { + let currentProjectAttachment = + project.attachments[pointerToAttachment]; + if ( + currentProjectAttachment.type == + CONSTANTS.common.ATTACHMENT_TYPE_LINK + ) { + projectLinkAttachments.push(currentProjectAttachment); + } else { + projectAttachments.push(currentProjectAttachment.sourcePath); + } + } - categories.forEach(category => { - if (category.value && category.value !== "") { - categoryIds.push(category.value); - } - }); + let projectAttachmentsUrl = await _attachmentInformation( + projectAttachments, + projectLinkAttachments, + project.attachments, + CONSTANTS.common.PROJECT_ATTACHMENT + ); + if ( + projectAttachmentsUrl.data && + projectAttachmentsUrl.data.length > 0 + ) { + project.attachments = projectAttachmentsUrl.data; + } + } + + //task attachments + if (project.tasks && project.tasks.length > 0) { + //order task based on task sequence + if (project.taskSequence && project.taskSequence.length > 0) { + project.tasks = taskArrayBySequence( + project.tasks, + project.taskSequence, + "externalId" + ); + } - let categoryData = []; + let attachments = []; + let mapTaskIdToAttachment = {}; + let mapLinkAttachment = {}; - if (categoryIds.length > 0) { + for (let task = 0; task < project.tasks.length; task++) { + let currentTask = project.tasks[task]; - categoryData = - await projectCategoriesQueries.categoryDocuments({ - _id: { $in: categoryIds } - }, ["name", "externalId"]); + if (currentTask.attachments && currentTask.attachments.length > 0) { + for ( + let attachment = 0; + attachment < currentTask.attachments.length; + attachment++ + ) { + let currentAttachment = currentTask.attachments[attachment]; - if (!categoryData.length > 0) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.CATEGORY_NOT_FOUND - } + if ( + currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK + ) { + if ( + !Array.isArray(mapLinkAttachment[currentTask._id]) || + !mapLinkAttachment[currentTask._id].length + ) { + mapLinkAttachment[currentTask._id] = []; } + mapLinkAttachment[currentTask._id].push(currentAttachment); + } else { + attachments.push(currentAttachment.sourcePath); + } + + if ( + !mapTaskIdToAttachment[currentAttachment.sourcePath] && + currentAttachment.type != CONSTANTS.common.ATTACHMENT_TYPE_LINK + ) { + mapTaskIdToAttachment[currentAttachment.sourcePath] = { + taskId: currentTask._id, + }; + } } + } + } - let categoryInternalIdToData = {}; - - if (categoryData.length > 0) { - - categoryData.forEach(category => { - categoryInternalIdToData[category._id.toString()] = category; - }); - } + let taskAttachmentsUrl = await _attachmentInformation( + attachments, + mapLinkAttachment, + [], + CONSTANTS.common.TASK_ATTACHMENT, + mapTaskIdToAttachment, + project.tasks + ); + if (taskAttachmentsUrl.data && taskAttachmentsUrl.data.length > 0) { + project.tasks = taskAttachmentsUrl.data; + } + } - const categoriesData = categories.map(category => { - let categoryData = {}; + project.status = project.status + ? project.status + : CONSTANTS.common.NOT_STARTED_STATUS; - if ( - category.value && - category.value !== "" && - categoryInternalIdToData[category.value] - ) { - categoryData = categoryInternalIdToData[category.value]; - } else { - categoryData = { - name: category.label, - externalId: "", - _id: "" - } - } + if (project.metaInformation) { + Object.keys(project.metaInformation).forEach((projectMetaKey) => { + project[projectMetaKey] = project.metaInformation[projectMetaKey]; + }); + } + + delete project.metaInformation; + delete project.__v; + delete project.entityInformation; + delete project.solutionInformation; + delete project.programInformation; + + return resolve({ + success: true, + data: project, + }); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); +} - return categoryData; - }); +function taskArrayBySequence(taskArray, sequenceArray, key) { + var map = sequenceArray.reduce( + (acc, value, index) => ((acc[value] = index + 1), acc), + {} + ); + const sortedTaskArray = taskArray.sort( + (a, b) => (map[a[key]] || Infinity) - (map[b[key]] || Infinity) + ); + return sortedTaskArray; +} - return resolve({ - success: true, - data: categoriesData - }); +/** + * Attachment information of project. + * @method + * @name _attachmentInformation + * @param {Array} attachments - attachments data. + * @param {String} type - project or task attachement. + * @returns {Object} Project attachments. + */ +function _attachmentInformation( + attachmentWithSourcePath = [], + linkAttachments = [], + attachments = [], + type, + mapTaskIdToAttachment = {}, + tasks = [] +) { + return new Promise(async (resolve, reject) => { + try { + let attachmentOrTask = []; + + if (attachmentWithSourcePath && attachmentWithSourcePath.length > 0) { + let attachmentsUrl = await coreService.getDownloadableUrl({ + filePaths: attachmentWithSourcePath, + }); - } catch (error) { - return resolve({ - message: error.message, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - data: {} - }); + if (!attachmentsUrl.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND, + }; } - }) -} -/** - * Entities information for project. - * @method - * @name _entitiesInformation - * @param {String} entityIds - entity id. - * @returns {Object} Project entity information. -*/ + if (attachmentsUrl.data && attachmentsUrl.data.length > 0) { + if (type === CONSTANTS.common.PROJECT_ATTACHMENT) { + attachmentsUrl.data.forEach((eachAttachment) => { + let projectAttachmentIndex = attachments.findIndex( + (attachmentData) => + attachmentData.sourcePath == eachAttachment.filePath + ); + + if (projectAttachmentIndex > -1) { + attachments[projectAttachmentIndex].url = eachAttachment.url; + } + }); + } else { + attachmentsUrl.data.forEach((taskAttachments) => { + let taskIndex = tasks.findIndex( + (task) => + task._id === + mapTaskIdToAttachment[taskAttachments.filePath].taskId + ); + + if (taskIndex > -1) { + let attachmentIndex = tasks[taskIndex].attachments.findIndex( + (attachment) => + attachment.sourcePath === taskAttachments.filePath + ); -function _entitiesInformation(entityIds) { - return new Promise(async (resolve, reject) => { - try { - let locationIds = []; - let locationCodes = []; - let entityInformations = []; - entityIds.forEach(entity=>{ - if (UTILS.checkValidUUID(entity)) { - locationIds.push(entity); - } else { - locationCodes.push(entity); + if (attachmentIndex > -1) { + tasks[taskIndex].attachments[attachmentIndex].url = + taskAttachments.url; } + } }); + } + } + } - if ( locationIds.length > 0 ) { - let bodyData = { - "id" : locationIds - } - let entityData = await userProfileService.locationSearch( bodyData, formatResult = true); - if ( entityData.success ) { - entityInformations = entityData.data; - } + if (linkAttachments && linkAttachments.length > 0) { + if (type === CONSTANTS.common.PROJECT_ATTACHMENT) { + attachments.concat(linkAttachments); + } else { + Object.keys(linkAttachments).forEach((eachTaskId) => { + let taskIdIndex = tasks.findIndex( + (task) => task._id === eachTaskId + ); + if (taskIdIndex > -1) { + tasks[taskIdIndex].attachments.concat( + linkAttachments[eachTaskId] + ); } + }); + } + } - if ( locationCodes.length > 0 ) { - let bodyData = { - "code" : locationCodes - } - let entityData = await userProfileService.locationSearch( bodyData , formatResult = true ); - if ( entityData.success ) { - entityInformations = entityInformations.concat(entityData.data); - } - } - - if ( !entityInformations.length > 0 ) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND - } - } - let entitiesData = []; - if ( entityInformations.length > 0 ) { - entitiesData = await _entitiesMetaInformation(entityInformations); - } - - return resolve({ - success: true, - data: entitiesData - }); + attachmentOrTask = + type === CONSTANTS.common.PROJECT_ATTACHMENT ? attachments : tasks; - } catch (error) { - return resolve({ - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - message: error.message, - data: [] - }); - } - }) + return resolve({ + success: true, + data: attachmentOrTask, + }); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); } /** - * Assessment details - * @method - * @name _assessmentDetails - * @param {Object} assessmentData - Assessment data. - * @returns {Object} -*/ - -function _assessmentDetails(assessmentData) { - return new Promise(async (resolve, reject) => { - try { + * Task of project. + * @method + * @name _projectTask + * @param {Array} tasks - tasks data. + * @param {String} userId - logged in user id. + * @returns {Object} Project task. + */ - let result = {}; +function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { + tasks.forEach((singleTask) => { + singleTask.externalId = singleTask.externalId + ? singleTask.externalId + : singleTask.name.toLowerCase(); + singleTask.type = singleTask.type + ? singleTask.type + : CONSTANTS.common.SIMPLE_TASK_TYPE; + singleTask.status = singleTask.status + ? singleTask.status + : CONSTANTS.common.NOT_STARTED_STATUS; + singleTask.isDeleted = singleTask.isDeleted ? singleTask.isDeleted : false; + + if (!singleTask.hasOwnProperty("isDeletable")) { + singleTask.isDeletable = true; + } + if (UTILS.isValidMongoId(singleTask._id.toString())) { + singleTask.referenceId = singleTask._id.toString(); + } + singleTask.createdAt = singleTask.createdAt + ? singleTask.createdAt + : new Date(); + singleTask.updatedAt = new Date(); + singleTask._id = UTILS.isValidMongoId(singleTask._id.toString()) + ? uuidv4() + : singleTask._id; + singleTask.isImportedFromLibrary = isImportedFromLibrary; + singleTask.syncedAt = new Date(); + + if (singleTask.startDate) { + singleTask.startDate = singleTask.startDate; + } - if (assessmentData.project) { + if (singleTask.endDate) { + singleTask.endDate = singleTask.endDate; + } - let templateTasks = - await projectTemplateTaskQueries.taskDocuments({ - externalId: assessmentData.project.taskId - }, ["_id"]) + if (singleTask.visibleIf && singleTask.visibleIf.length > 0) { + if (parentTaskId !== "") { + singleTask.visibleIf.forEach((task) => { + task._id = parentTaskId; + }); + } + } - if (templateTasks.length > 0) { - assessmentData.project.taskId = templateTasks[0]._id; - } - } + removeFieldsFromRequest.forEach((removeField) => { + delete singleTask[removeField]; + }); - if (assessmentData.solutionDetails.isReusable) { - - let createdAssessment = - await surveyService.createAssessmentSolutionFromTemplate( - assessmentData.token, - assessmentData.solutionDetails._id, - { - name: assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), - description: assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), - program: { - _id: assessmentData.programId, - name: "" - }, - entities: [assessmentData.entityId], - project: assessmentData.project - } - ); + if (singleTask.children) { + _projectTask(singleTask.children, isImportedFromLibrary, singleTask._id); + } else { + singleTask.children = []; + } + }); - if (!createdAssessment.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.COULD_NOT_CREATE_ASSESSMENT_SOLUTION - } - } + return tasks; +} - result["solutionId"] = createdAssessment.data._id; +/** + * Project categories information. + * @method + * @name _projectCategories + * @param {Array} categories - Categories data. + * @returns {Object} Project categories information. + */ - } else { +function _projectCategories(categories) { + return new Promise(async (resolve, reject) => { + try { + let categoryIds = []; - let assignedAssessmentToUser = - await surveyService.createEntityAssessors( - assessmentData.token, - assessmentData.solutionDetails.programId, - assessmentData.solutionDetails._id, - [assessmentData.entityId] - ); + categories.forEach((category) => { + if (category.value && category.value !== "") { + categoryIds.push(category.value); + } + }); + + let categoryData = []; + + if (categoryIds.length > 0) { + categoryData = await projectCategoriesQueries.categoryDocuments( + { + _id: { $in: categoryIds }, + }, + ["name", "externalId"] + ); + + if (!categoryData.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.CATEGORY_NOT_FOUND, + }; + } + } - if (!assignedAssessmentToUser.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.FAILED_TO_ASSIGNED_ASSESSMENT_TO_USER - } - } + let categoryInternalIdToData = {}; - let entitiesAddedToSolution = - await surveyService.addEntitiesToSolution( - assessmentData.token, - assessmentData.solutionDetails._id, - [assessmentData.entityId.toString()] - ); + if (categoryData.length > 0) { + categoryData.forEach((category) => { + categoryInternalIdToData[category._id.toString()] = category; + }); + } - if (!entitiesAddedToSolution.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.FAILED_TO_ADD_ENTITY_TO_SOLUTION - } - } + const categoriesData = categories.map((category) => { + let categoryData = {}; - let solutionUpdated = - await surveyService.updateSolution( - assessmentData.token, - { - "project": assessmentData.project, - referenceFrom: "project" - }, - assessmentData.solutionDetails.externalId - ); + if ( + category.value && + category.value !== "" && + categoryInternalIdToData[category.value] + ) { + categoryData = categoryInternalIdToData[category.value]; + } else { + categoryData = { + name: category.label, + externalId: "", + _id: "", + }; + } - if (!solutionUpdated.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.SOLUTION_NOT_UPDATED - } - } + return categoryData; + }); - result["solutionId"] = assessmentData.solutionDetails._id; - } + return resolve({ + success: true, + data: categoriesData, + }); + } catch (error) { + return resolve({ + message: error.message, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + data: {}, + }); + } + }); +} - return resolve({ - success: true, - data: result - }); +/** + * Entities information for project. + * @method + * @name _entitiesInformation + * @param {String} entityIds - entity id. + * @returns {Object} Project entity information. + */ - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }); +function _entitiesInformation(entityIds) { + return new Promise(async (resolve, reject) => { + try { + let locationIds = []; + let locationCodes = []; + let entityInformations = []; + entityIds.forEach((entity) => { + if (UTILS.checkValidUUID(entity)) { + locationIds.push(entity); + } else { + locationCodes.push(entity); + } + }); + + if (locationIds.length > 0) { + let bodyData = { + id: locationIds, + }; + let entityData = await userProfileService.locationSearch( + bodyData, + (formatResult = true) + ); + if (entityData.success) { + entityInformations = entityData.data; + } + } + + if (locationCodes.length > 0) { + let bodyData = { + code: locationCodes, + }; + let entityData = await userProfileService.locationSearch( + bodyData, + (formatResult = true) + ); + if (entityData.success) { + entityInformations = entityInformations.concat(entityData.data); } - }) + } + + if (!entityInformations.length > 0) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND, + }; + } + let entitiesData = []; + if (entityInformations.length > 0) { + entitiesData = await _entitiesMetaInformation(entityInformations); + } + + return resolve({ + success: true, + data: entitiesData, + }); + } catch (error) { + return resolve({ + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + message: error.message, + data: [], + }); + } + }); } /** - * Observation details - * @method - * @name _observationDetails - * @param {Object} observationData - Observation data. - * @returns {Object} -*/ - -function _observationDetails(observationData, userRoleAndProfileInformation = {}) { - return new Promise(async (resolve, reject) => { - try { - - let result = {}; - - if (observationData.project) { - - let templateTasks = - await projectTemplateTaskQueries.taskDocuments({ - externalId: observationData.project.taskId - }, ["_id"]) + * Assessment details + * @method + * @name _assessmentDetails + * @param {Object} assessmentData - Assessment data. + * @returns {Object} + */ - if (templateTasks.length > 0) { - observationData.project.taskId = templateTasks[0]._id; - } +function _assessmentDetails(assessmentData) { + return new Promise(async (resolve, reject) => { + try { + let result = {}; + + if (assessmentData.project) { + let templateTasks = await projectTemplateTaskQueries.taskDocuments( + { + externalId: assessmentData.project.taskId, + }, + ["_id"] + ); + + if (templateTasks.length > 0) { + assessmentData.project.taskId = templateTasks[0]._id; + } + } + + if (assessmentData.solutionDetails.isReusable) { + let createdAssessment = + await surveyService.createAssessmentSolutionFromTemplate( + assessmentData.token, + assessmentData.solutionDetails._id, + { + name: + assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), + description: + assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), + program: { + _id: assessmentData.programId, + name: "", + }, + entities: [assessmentData.entityId], + project: assessmentData.project, } + ); + + if (!createdAssessment.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: + CONSTANTS.apiResponses.COULD_NOT_CREATE_ASSESSMENT_SOLUTION, + }; + } - if (observationData.solutionDetails.isReusable) { - - let observationCreatedFromTemplate = - await surveyService.createObservationFromSolutionTemplate( - observationData.token, - observationData.solutionDetails._id, - { - name: observationData.solutionDetails.name + "-" + UTILS.epochTime(), - description: observationData.solutionDetails.name + "-" + UTILS.epochTime(), - program: { - _id: observationData.programId, - name: "" - }, - status: CONSTANTS.common.PUBLISHED_STATUS, - entities: [observationData.entityId], - project: observationData.project - } - ); - - if (!observationCreatedFromTemplate.success) { - throw { - status: HTTP_STATUS_CODE['bad_request'].status, - message: CONSTANTS.apiResponses.OBSERVATION_NOT_CREATED - } - } + result["solutionId"] = createdAssessment.data._id; + } else { + let assignedAssessmentToUser = + await surveyService.createEntityAssessors( + assessmentData.token, + assessmentData.solutionDetails.programId, + assessmentData.solutionDetails._id, + [assessmentData.entityId] + ); + + if (!assignedAssessmentToUser.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: + CONSTANTS.apiResponses.FAILED_TO_ASSIGNED_ASSESSMENT_TO_USER, + }; + } - result["solutionId"] = observationCreatedFromTemplate.data._id; - result["observationId"] = observationCreatedFromTemplate.data.observationId; + let entitiesAddedToSolution = await surveyService.addEntitiesToSolution( + assessmentData.token, + assessmentData.solutionDetails._id, + [assessmentData.entityId.toString()] + ); + + if (!entitiesAddedToSolution.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.FAILED_TO_ADD_ENTITY_TO_SOLUTION, + }; + } - } else { + let solutionUpdated = await surveyService.updateSolution( + assessmentData.token, + { + project: assessmentData.project, + referenceFrom: "project", + }, + assessmentData.solutionDetails.externalId + ); + + if (!solutionUpdated.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.SOLUTION_NOT_UPDATED, + }; + } - let startDate = new Date(); - let endDate = new Date(); - endDate.setFullYear(endDate.getFullYear() + 1); - - let observation = { - name: observationData.solutionDetails.name, - description: observationData.solutionDetails.name, - status: CONSTANTS.common.PUBLISHED_STATUS, - startDate: startDate, - endDate: endDate, - entities: [observationData.entityId], - project: observationData.project - }; + result["solutionId"] = assessmentData.solutionDetails._id; + } - let observationCreated = await surveyService.createObservation( - observationData.token, - observationData.solutionDetails._id, - observation, - userRoleAndProfileInformation && Object.keys(userRoleAndProfileInformation).length > 0 ? userRoleAndProfileInformation : {} - ); + return resolve({ + success: true, + data: result, + }); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); +} - if ( observationCreated.success ) { - result["observationId"] = observationCreated.data._id; - } +/** + * Observation details + * @method + * @name _observationDetails + * @param {Object} observationData - Observation data. + * @returns {Object} + */ - result["solutionId"] = observationData.solutionDetails._id; - +function _observationDetails( + observationData, + userRoleAndProfileInformation = {} +) { + return new Promise(async (resolve, reject) => { + try { + let result = {}; + + if (observationData.project) { + let templateTasks = await projectTemplateTaskQueries.taskDocuments( + { + externalId: observationData.project.taskId, + }, + ["_id"] + ); + + if (templateTasks.length > 0) { + observationData.project.taskId = templateTasks[0]._id; + } + } + + if (observationData.solutionDetails.isReusable) { + let observationCreatedFromTemplate = + await surveyService.createObservationFromSolutionTemplate( + observationData.token, + observationData.solutionDetails._id, + { + name: + observationData.solutionDetails.name + "-" + UTILS.epochTime(), + description: + observationData.solutionDetails.name + "-" + UTILS.epochTime(), + program: { + _id: observationData.programId, + name: "", + }, + status: CONSTANTS.common.PUBLISHED_STATUS, + entities: [observationData.entityId], + project: observationData.project, } + ); - return resolve({ - success: true, - data: result - }); + if (!observationCreatedFromTemplate.success) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.OBSERVATION_NOT_CREATED, + }; + } - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status - }); + result["solutionId"] = observationCreatedFromTemplate.data._id; + result["observationId"] = + observationCreatedFromTemplate.data.observationId; + } else { + let startDate = new Date(); + let endDate = new Date(); + endDate.setFullYear(endDate.getFullYear() + 1); + + let observation = { + name: observationData.solutionDetails.name, + description: observationData.solutionDetails.name, + status: CONSTANTS.common.PUBLISHED_STATUS, + startDate: startDate, + endDate: endDate, + entities: [observationData.entityId], + project: observationData.project, + }; + + let observationCreated = await surveyService.createObservation( + observationData.token, + observationData.solutionDetails._id, + observation, + userRoleAndProfileInformation && + Object.keys(userRoleAndProfileInformation).length > 0 + ? userRoleAndProfileInformation + : {} + ); + + if (observationCreated.success) { + result["observationId"] = observationCreated.data._id; } - }) + + result["solutionId"] = observationData.solutionDetails._id; + } + + return resolve({ + success: true, + data: result, + }); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + }); + } + }); } /** - * Observation details - * @method - * @name _entitiesMetaInformation - * @param {Object} entitiesData - entities data. - * @returns {Object} - entities metadata. -*/ + * Observation details + * @method + * @name _entitiesMetaInformation + * @param {Object} entitiesData - entities data. + * @returns {Object} - entities metadata. + */ function _entitiesMetaInformation(entitiesData) { - return new Promise(async (resolve, reject) => { - let entityInformation = [] - for ( let index = 0; index < entitiesData.length; index++ ) { - let entityHierarchy = await userProfileService.getParentEntities( entitiesData[index]._id ); - entitiesData[index].metaInformation.hierarchy = entityHierarchy; - entitiesData[index].metaInformation._id = entitiesData[index]._id; - entitiesData[index].metaInformation.entityType = entitiesData[index].entityType; - entitiesData[index].metaInformation.registryDetails = entitiesData[index].registryDetails; - entityInformation.push(entitiesData[index].metaInformation) - } - - return resolve (entityInformation); - }) -} + return new Promise(async (resolve, reject) => { + let entityInformation = []; + for (let index = 0; index < entitiesData.length; index++) { + let entityHierarchy = await userProfileService.getParentEntities( + entitiesData[index]._id + ); + entitiesData[index].metaInformation.hierarchy = entityHierarchy; + entitiesData[index].metaInformation._id = entitiesData[index]._id; + entitiesData[index].metaInformation.entityType = + entitiesData[index].entityType; + entitiesData[index].metaInformation.registryDetails = + entitiesData[index].registryDetails; + entityInformation.push(entitiesData[index].metaInformation); + } + return resolve(entityInformation); + }); +} /** - * Project Add And Sync Common information. - * @method - * @name _projectData - * @param {Array} data - Req data. - * @returns {Object} Project Add information. -*/ + * Project Add And Sync Common information. + * @method + * @name _projectData + * @param {Array} data - Req data. + * @returns {Object} Project Add information. + */ function _projectData(data) { - return new Promise(async (resolve, reject) => { - try { - - let projectData = {}; - if (data.categories && data.categories.length > 0) { - - let categories = - await _projectCategories(data.categories); - - if (!categories.success) { - return resolve(categories); - } - - projectData.categories = categories.data; - } + return new Promise(async (resolve, reject) => { + try { + let projectData = {}; + if (data.categories && data.categories.length > 0) { + let categories = await _projectCategories(data.categories); + + if (!categories.success) { + return resolve(categories); + } - if (data.startDate) { - projectData["startDate"] = data.startDate; - } + projectData.categories = categories.data; + } - if (data.endDate) { - projectData["endDate"] = data.endDate; - } + if (data.startDate) { + projectData["startDate"] = data.startDate; + } - if (data.learningResources) { - projectData.learningResources = data.learningResources; - } + if (data.endDate) { + projectData["endDate"] = data.endDate; + } - projectData.syncedAt = new Date(); + if (data.learningResources) { + projectData.learningResources = data.learningResources; + } - return resolve({ - success: true, - data: projectData - }); + projectData.syncedAt = new Date(); - } catch (error) { - return resolve({ - message: error.message, - status: - error.status ? - error.status : HTTP_STATUS_CODE['internal_server_error'].status, - success: false, - data: {} - }); - } - }) + return resolve({ + success: true, + data: projectData, + }); + } catch (error) { + return resolve({ + message: error.message, + status: error.status + ? error.status + : HTTP_STATUS_CODE["internal_server_error"].status, + success: false, + data: {}, + }); + } + }); } /** - * Validate & Update UserProfile in Projects. - * @method - * @name _updateUserProfileBasedOnUserRoleInfo - * @param {Object} userProfile - userProfile data. - * @param {Object} userRoleInformation - userRoleInformation data. - * @returns {Object} updated UserProfile information. -*/ - -function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) { - return new Promise(async (resolve, reject) => { - try { - - - let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles - - if(userRoleInformation.role) { // Check if userRoleInformation has role value. - let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. - - let resetCurrentUserProfileRoles = false; // Flag to reset current userProfile.profileUserTypes i.e. if current role in profile is not at all there in userRoleInformation.roles - // Check if userProfile.profileUserTypes exists and is an array of length > 0 - if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { - - // Loop through current roles in userProfile.profileUserTypes - for (let pointerToCurrentProfileUserTypes = 0; pointerToCurrentProfileUserTypes < userProfile.profileUserTypes.length; pointerToCurrentProfileUserTypes++) { - const currentProfileUserType = userProfile.profileUserTypes[pointerToCurrentProfileUserTypes]; - - if(currentProfileUserType.subType && currentProfileUserType.subType !== null) { // If the role has a subType - - // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. - if(!userRoleInformation.role.toUpperCase().includes(currentProfileUserType.subType.toUpperCase())) { - resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes - break; - } - } else { // If the role subType is null or is not there + * Validate & Update UserProfile in Projects. + * @method + * @name _updateUserProfileBasedOnUserRoleInfo + * @param {Object} userProfile - userProfile data. + * @param {Object} userRoleInformation - userRoleInformation data. + * @returns {Object} updated UserProfile information. + */ - // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. - if(!userRoleInformation.role.toUpperCase().includes(currentProfileUserType.type.toUpperCase())) { - resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes - break; - } - } - } - } - if(resetCurrentUserProfileRoles) { // Reset userProfile.profileUserTypes - userProfile.profileUserTypes = new Array; - } +function _updateUserProfileBasedOnUserRoleInfo( + userProfile, + userRoleInformation +) { + return new Promise(async (resolve, reject) => { + try { + let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles + + if (userRoleInformation.role) { + // Check if userRoleInformation has role value. + let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. + + let resetCurrentUserProfileRoles = false; // Flag to reset current userProfile.profileUserTypes i.e. if current role in profile is not at all there in userRoleInformation.roles + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if ( + userProfile.profileUserTypes && + Array.isArray(userProfile.profileUserTypes) && + userProfile.profileUserTypes.length > 0 + ) { + // Loop through current roles in userProfile.profileUserTypes + for ( + let pointerToCurrentProfileUserTypes = 0; + pointerToCurrentProfileUserTypes < + userProfile.profileUserTypes.length; + pointerToCurrentProfileUserTypes++ + ) { + const currentProfileUserType = + userProfile.profileUserTypes[pointerToCurrentProfileUserTypes]; - // Loop through each subRole in userRoleInformation - for (let pointerToRolesInUserInformation = 0; pointerToRolesInUserInformation < rolesInUserRoleInformation.length; pointerToRolesInUserInformation++) { - const subRole = rolesInUserRoleInformation[pointerToRolesInUserInformation]; - // Check if userProfile.profileUserTypes exists and is an array of length > 0 - if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { - if(!_.find(userProfile.profileUserTypes, { 'type': subRole.toLowerCase() }) && !_.find(userProfile.profileUserTypes, { 'subType': subRole.toLowerCase() })) { - updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes - if(subRole.toUpperCase() === "TEACHER") { // If subRole is not teacher - userProfile.profileUserTypes.push({ - "subType" : null, - "type" : "teacher" - }) - } else { // If subRole is not teacher - userProfile.profileUserTypes.push({ - "subType" : subRole.toLowerCase(), - "type" : "administrator" - }) - } - } - } else { // Make a new entry if userProfile.profileUserTypes is empty or does not exist. - updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes - userProfile.profileUserTypes = new Array; - if(subRole.toUpperCase() === "TEACHER") { // If subRole is teacher - userProfile.profileUserTypes.push({ - "subType" : null, - "type" : "teacher" - }) - } else { // If subRole is not teacher - userProfile.profileUserTypes.push({ - "subType" : subRole.toLowerCase(), - "type" : "administrator" - }) - } - } - } + if ( + currentProfileUserType.subType && + currentProfileUserType.subType !== null + ) { + // If the role has a subType + + // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. + if ( + !userRoleInformation.role + .toUpperCase() + .includes(currentProfileUserType.subType.toUpperCase()) + ) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } else { + // If the role subType is null or is not there + + // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. + if ( + !userRoleInformation.role + .toUpperCase() + .includes(currentProfileUserType.type.toUpperCase()) + ) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } } + } + } + if (resetCurrentUserProfileRoles) { + // Reset userProfile.profileUserTypes + userProfile.profileUserTypes = new Array(); + } - if(updateUserProfileRoleInformation) { // If profileUserTypes in userProfile was wrong and is updated as per userRoleInformation - userProfile.userRoleMismatchFoundAndUpdated = true; + // Loop through each subRole in userRoleInformation + for ( + let pointerToRolesInUserInformation = 0; + pointerToRolesInUserInformation < rolesInUserRoleInformation.length; + pointerToRolesInUserInformation++ + ) { + const subRole = + rolesInUserRoleInformation[pointerToRolesInUserInformation]; + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if ( + userProfile.profileUserTypes && + Array.isArray(userProfile.profileUserTypes) && + userProfile.profileUserTypes.length > 0 + ) { + if ( + !_.find(userProfile.profileUserTypes, { + type: subRole.toLowerCase(), + }) && + !_.find(userProfile.profileUserTypes, { + subType: subRole.toLowerCase(), + }) + ) { + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + if (subRole.toUpperCase() === "TEACHER") { + // If subRole is not teacher + userProfile.profileUserTypes.push({ + subType: null, + type: "teacher", + }); + } else { + // If subRole is not teacher + userProfile.profileUserTypes.push({ + subType: subRole.toLowerCase(), + type: "administrator", + }); + } } - - // Create location only object from userRoleInformation - let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); - - // All location keys from userRoleInformation - let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); - - let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values - - // Loop through all location keys. - for (let pointerToUserRoleInfromationLocationKeys = 0; pointerToUserRoleInfromationLocationKeys < userRoleInfomrationLocationKeys.length; pointerToUserRoleInfromationLocationKeys++) { - - const locationType = userRoleInfomrationLocationKeys[pointerToUserRoleInfromationLocationKeys]; // e.g. state, district, school - const locationValue = userRoleInformationLocationObject[locationType]; // Location UUID values or school code. - - // Check if userProfile.userLocations exists and is an array of length > 0 - if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { - - if(locationType === "school") { // If location type school exist check if same is there in userProfile.userLocations - if(!_.find(userProfile.userLocations, { 'type': "school", 'code': locationValue })) { - updateUserProfileLocationInformation = true; // School does not exist in userProfile.userLocations, update entire userProfile.userLocations - break; - } - } else { // Check if location type is there in userProfile.userLocations and has same value as userRoleInformation - if(!_.find(userProfile.userLocations, { 'type': locationType, 'id': locationValue })) { - updateUserProfileLocationInformation = true; // Location does not exist in userProfile.userLocations, update entire userProfile.userLocations - break; - } - } - } else { - updateUserProfileLocationInformation = true; - break; - } + } else { + // Make a new entry if userProfile.profileUserTypes is empty or does not exist. + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + userProfile.profileUserTypes = new Array(); + if (subRole.toUpperCase() === "TEACHER") { + // If subRole is teacher + userProfile.profileUserTypes.push({ + subType: null, + type: "teacher", + }); + } else { + // If subRole is not teacher + userProfile.profileUserTypes.push({ + subType: subRole.toLowerCase(), + type: "administrator", + }); } - - if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { - if(userProfile.userLocations.length != userRoleInfomrationLocationKeys.length) { - updateUserProfileLocationInformation = true; - } + } + } + } + + if (updateUserProfileRoleInformation) { + // If profileUserTypes in userProfile was wrong and is updated as per userRoleInformation + userProfile.userRoleMismatchFoundAndUpdated = true; + } + + // Create location only object from userRoleInformation + let userRoleInformationLocationObject = _.omit(userRoleInformation, [ + "role", + ]); + + // All location keys from userRoleInformation + let userRoleInfomrationLocationKeys = Object.keys( + userRoleInformationLocationObject + ); + + let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values + + // Loop through all location keys. + for ( + let pointerToUserRoleInfromationLocationKeys = 0; + pointerToUserRoleInfromationLocationKeys < + userRoleInfomrationLocationKeys.length; + pointerToUserRoleInfromationLocationKeys++ + ) { + const locationType = + userRoleInfomrationLocationKeys[ + pointerToUserRoleInfromationLocationKeys + ]; // e.g. state, district, school + const locationValue = userRoleInformationLocationObject[locationType]; // Location UUID values or school code. + + // Check if userProfile.userLocations exists and is an array of length > 0 + if ( + userProfile.userLocations && + Array.isArray(userProfile.userLocations) && + userProfile.userLocations.length > 0 + ) { + if (locationType === "school") { + // If location type school exist check if same is there in userProfile.userLocations + if ( + !_.find(userProfile.userLocations, { + type: "school", + code: locationValue, + }) + ) { + updateUserProfileLocationInformation = true; // School does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; } + } else { + // Check if location type is there in userProfile.userLocations and has same value as userRoleInformation + if ( + !_.find(userProfile.userLocations, { + type: locationType, + id: locationValue, + }) + ) { + updateUserProfileLocationInformation = true; // Location does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } + } else { + updateUserProfileLocationInformation = true; + break; + } + } + + if ( + userProfile.userLocations && + Array.isArray(userProfile.userLocations) && + userProfile.userLocations.length > 0 + ) { + if ( + userProfile.userLocations.length != + userRoleInfomrationLocationKeys.length + ) { + updateUserProfileLocationInformation = true; + } + } + + // If userProfile.userLocations has to be updated, get all values and set in userProfile. + if (updateUserProfileLocationInformation) { + //update userLocations in userProfile + let locationIds = []; + let locationCodes = []; + let userLocations = new Array(); + + userRoleInfomrationLocationKeys.forEach((requestedDataKey) => { + if ( + UTILS.checkValidUUID( + userRoleInformationLocationObject[requestedDataKey] + ) + ) { + locationIds.push( + userRoleInformationLocationObject[requestedDataKey] + ); + } else { + locationCodes.push( + userRoleInformationLocationObject[requestedDataKey] + ); + } + }); - // If userProfile.userLocations has to be updated, get all values and set in userProfile. - if(updateUserProfileLocationInformation) { - - //update userLocations in userProfile - let locationIds = []; - let locationCodes = []; - let userLocations = new Array; - - userRoleInfomrationLocationKeys.forEach( requestedDataKey => { - if (UTILS.checkValidUUID(userRoleInformationLocationObject[requestedDataKey])) { - locationIds.push(userRoleInformationLocationObject[requestedDataKey]); - } else { - locationCodes.push(userRoleInformationLocationObject[requestedDataKey]); - } - }) - - //query for fetch location using id - if ( locationIds.length > 0 ) { - let locationQuery = { - "id" : locationIds - } - - let entityData = await userProfileService.locationSearch(locationQuery); - if ( entityData.success ) { - userLocations = entityData.data; - } - } - - // query for fetch location using code - if ( locationCodes.length > 0 ) { - let codeQuery = { - "code" : locationCodes - } - - let entityData = await userProfileService.locationSearch(codeQuery); - if ( entityData.success ) { - userLocations = userLocations.concat(entityData.data); - } - } + //query for fetch location using id + if (locationIds.length > 0) { + let locationQuery = { + id: locationIds, + }; + + let entityData = await userProfileService.locationSearch( + locationQuery + ); + if (entityData.success) { + userLocations = entityData.data; + } + } - if ( userLocations.length > 0 ) { - userProfile["userLocations"] = userLocations; - userProfile.userLocationsMismatchFoundAndUpdated = true; // If userLocations in userProfile was wrong and is updated as per userRoleInformation - } - } + // query for fetch location using code + if (locationCodes.length > 0) { + let codeQuery = { + code: locationCodes, + }; - return resolve({ - success: true, - profileMismatchFound : (updateUserProfileLocationInformation || updateUserProfileRoleInformation) ? true : false, - data: userProfile - }); + let entityData = await userProfileService.locationSearch(codeQuery); + if (entityData.success) { + userLocations = userLocations.concat(entityData.data); + } + } - } catch (error) { - return resolve({ - status: error.status || HTTP_STATUS_CODE['internal_server_error'].status, - message: error.message || HTTP_STATUS_CODE['internal_server_error'].message, - data : false - }); + if (userLocations.length > 0) { + userProfile["userLocations"] = userLocations; + userProfile.userLocationsMismatchFoundAndUpdated = true; // If userLocations in userProfile was wrong and is updated as per userRoleInformation } - }) -} \ No newline at end of file + } + + return resolve({ + success: true, + profileMismatchFound: + updateUserProfileLocationInformation || + updateUserProfileRoleInformation + ? true + : false, + data: userProfile, + }); + } catch (error) { + return resolve({ + status: + error.status || HTTP_STATUS_CODE["internal_server_error"].status, + message: + error.message || HTTP_STATUS_CODE["internal_server_error"].message, + data: false, + }); + } + }); +} From c587ecd93d591eab5a1e848970bb4537e8ae57c1 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Nov 2023 14:17:24 +0530 Subject: [PATCH 315/373] Fixing Prod Issue --- .../updateDistrictNameInProjects/Readme.md | 17 ++ .../updateDistrictName.js | 181 ++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 migrations/updateDistrictNameInProjects/Readme.md create mode 100644 migrations/updateDistrictNameInProjects/updateDistrictName.js diff --git a/migrations/updateDistrictNameInProjects/Readme.md b/migrations/updateDistrictNameInProjects/Readme.md new file mode 100644 index 00000000..09a764f3 --- /dev/null +++ b/migrations/updateDistrictNameInProjects/Readme.md @@ -0,0 +1,17 @@ +## Migrations + +#### Steps to run the script files + +In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. + +This script is designed to update project documents specifically for cases where there is a mismatch in district names. It will only affect the IDs specified in the script. + +### Step 1: + + Navigate to /opt/projects/updateDistrictNameInProjects/ + +### Step 2: + +Run the script to update projects. + + node updateDistrictName.js diff --git a/migrations/updateDistrictNameInProjects/updateDistrictName.js b/migrations/updateDistrictNameInProjects/updateDistrictName.js new file mode 100644 index 00000000..00b10ab1 --- /dev/null +++ b/migrations/updateDistrictNameInProjects/updateDistrictName.js @@ -0,0 +1,181 @@ +/** + * name : updateUserProfileInProjects.js + * author : Priyanka Pradeep + * created-date : 10-Nov-2022 + * Description : Migration script for update userProfile in project + */ + +const path = require("path"); +let rootPath = path.join(__dirname, "../../"); +require("dotenv").config({ path: rootPath + "/.env" }); + +let _ = require("lodash"); +let mongoUrl = process.env.MONGODB_URL; +let dbName = mongoUrl.split("/").pop(); +let url = mongoUrl.split(dbName)[0]; +var MongoClient = require("mongodb").MongoClient; +var ObjectId = require("mongodb").ObjectID; + +var fs = require("fs"); +const request = require("request"); + +// const userServiceUrl = "http://learner-service:9000"; +const userServiceUrl = "https://staging.sunbirded.org/api/data/"; +const endPoint = "/v1/location/search"; + +(async () => { + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + let updatedProjectIds = []; + + let projectIds = [ + new ObjectId("629739efe95af10009e7e57c"), + new ObjectId("6299eb19e95af10009e8e28f"), + new ObjectId("629a34b3e95af10009e91338"), + new ObjectId("629a3555e95af10009e913a6"), + new ObjectId("62b0416910889b000746d088"), + new ObjectId("62b2a009cd5f3c00077a1c47"), + new ObjectId("62b56b29cd5f3c00077a3282"), + new ObjectId("62b98078cd5f3c00077a4814"), + new ObjectId("63019b518f78ad0007651260"), + new ObjectId("6307813b8f78ad0007652524"), + new ObjectId("62985b30e95af10009e81ea0"), + new ObjectId("62985b345e195a0007d8fff0"), + new ObjectId("62985b365e195a0007d8fff4"), + ]; + + let filedMissmatch = "district"; + + //get project information from db + let projectDocuments = await db + .collection("projects") + .find({ + _id: { $in: projectIds }, + }) + .project({ + _id: 1, + userProfile: 1, + userRoleInformation: 1, + }) + .toArray(); + let updateProjectDocument = []; + + for (let count = 0; count < projectDocuments.length; count++) { + let filterData = { + id: projectDocuments[count].userRoleInformation[filedMissmatch], + }; + let correctDistrictData = await locationSearch(filterData); + let userLocationsWithCorrectData = []; + if (correctDistrictData.success) { + let userLocations = projectDocuments[count].userProfile.userLocations; + userLocationsWithCorrectData = userLocations.filter(function ( + locations + ) { + return ( + locations.id !== + projectDocuments[count].userRoleInformation[filedMissmatch] + ); + }); + userLocationsWithCorrectData.push(...correctDistrictData.data); + } + if (userLocationsWithCorrectData > 0) { + let updateObject = { + updateOne: { + filter: { + _id: projectDocuments[count]._id, + }, + update: { + $set: { + "userProfile.userLocations": userLocationsWithCorrectData, + }, + }, + }, + }; + updateProjectDocument.push(updateObject); + updatedProjectIds.push(projectDocuments[count]._id); + } + } + // will create BulkWrite Query to otimize excution + if (updateProjectDocument > 0) { + await db.collection("projects").bulkWrite(updateProjectDocument); + } + fs.writeFile( + `updatedProjectIds.json`, + + JSON.stringify(updatedProjectIds), + + function (err) { + if (err) { + console.error("Crap happens"); + } + } + ); + // used to get location information from learn service + function locationSearch(filterData) { + return new Promise(async (resolve, reject) => { + try { + let bodyData = {}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = filterData; + const url = userServiceUrl + endPoint; + const options = { + headers: { + "content-type": "application/json", + }, + json: bodyData, + }; + + request.post(url, options, requestCallback); + + let result = { + success: true, + }; + + function requestCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = data.body; + if ( + response.responseCode === "OK" && + response.result && + response.result.response && + response.result.response.length > 0 + ) { + let entityResult = new Array(); + response.result.response.map((entityData) => { + let entity = _.omit(entityData, ["identifier"]); + entityResult.push(entity); + }); + result["data"] = entityResult; + result["count"] = response.result.count; + } else { + result.success = false; + } + } + return resolve(result); + } + + setTimeout(function () { + return resolve( + (result = { + success: false, + }) + ); + }, 5000); + } catch (error) { + return reject(error); + } + }); + } + + //write updated project ids to file + + console.log("Updated Project Count : ", updatedProjectIds.length); + console.log("completed"); + connection.close(); + } catch (error) { + console.log(error); + } +})().catch((err) => console.error(err)); From b0882438898fb869058bd370021548e8791b545e Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Nov 2023 14:18:22 +0530 Subject: [PATCH 316/373] Fixing Prod Issue --- .../Readme.md | 17 + .../updateProjectWithProfileData.js | 449 ++++++++++++++++++ 2 files changed, 466 insertions(+) create mode 100644 migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md create mode 100644 migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js diff --git a/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md new file mode 100644 index 00000000..b73efeeb --- /dev/null +++ b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md @@ -0,0 +1,17 @@ +## Migrations + +#### Steps to run the script files + +In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. + +This script will update projects in cases where the user profile is missing and there is a mismatch between userProfile and userRoleInformations. + +### Step 1: + + Navigate to /opt/projects/updateUserProfileAndMissMatchOfRoleInformation/ + +### Step 2: + +Run the script to update projects. + + node updateProjectWithProfileData.js diff --git a/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js b/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js new file mode 100644 index 00000000..037795f8 --- /dev/null +++ b/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js @@ -0,0 +1,449 @@ +/** + * name : updateUserProfileInProjects.js + * author : Priyanka Pradeep + * created-date : 10-Nov-2022 + * Description : Migration script for update userProfile in project + */ + +const path = require("path"); +let rootPath = path.join(__dirname, "../../"); +require("dotenv").config({ path: rootPath + "/.env" }); + +let _ = require("lodash"); +let mongoUrl = process.env.MONGODB_URL; +let dbName = mongoUrl.split("/").pop(); +let url = mongoUrl.split(dbName)[0]; +var MongoClient = require("mongodb").MongoClient; +var ObjectId = require("mongodb").ObjectID; + +var fs = require("fs"); +const request = require("request"); + +const userServiceUrl = "http://learner-service:9000"; + +const endPoint = "/v1/location/search"; +const userReadEndpoint = "/private/user/v1/read"; + +(async () => { + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + let updatedProjectIds = { + userRoleInformationMissingProjectIds: [], + userProfileMissingProjectIds: [], + bothDataMissingProjectIds: [], + failedToGetProfileProjectIds: [], + }; + + // get all projects id where user profile is not there. + let projectDocument = await db + .collection("projects") + .find({ userProfile: { $exists: false } }) + .project({ _id: 1 }) + .toArray(); + + //make it in chunks so that we can iterate over + let chunkOfProjectDocument = _.chunk(projectDocument, 100); + let projectIds; + + for ( + let pointerToProject = 0; + pointerToProject < chunkOfProjectDocument.length; + pointerToProject++ + ) { + projectIds = await chunkOfProjectDocument[pointerToProject].map( + (projectDoc) => { + return projectDoc._id; + } + ); + + //get project documents along with userId, userProfile and userRoleInformation + let projectWithIncompleteData = await db + .collection("projects") + .find({ + _id: { $in: projectIds }, + }) + .project({ + _id: 1, + userId: 1, + userProfile: 1, + userRoleInformation: 1, + }) + .toArray(); + + let projectSeggregate = { + userProfileMissing: [], + userRoleInformationMissing: [], + bothDataMissing: [], + }; + + // seggredate project data based on condition + for (let count = 0; count < projectWithIncompleteData.length; count++) { + if ( + !projectWithIncompleteData[count].hasOwnProperty( + "userRoleInformation" + ) && + !projectWithIncompleteData[count].hasOwnProperty("userProfile") + ) { + projectSeggregate.bothDataMissing.push( + projectWithIncompleteData[count] + ); + } else if ( + !projectWithIncompleteData[count].hasOwnProperty( + "userRoleInformation" + ) + ) { + projectSeggregate.userRoleInformationMissing.push( + projectWithIncompleteData[count] + ); + } else if ( + !projectWithIncompleteData[count].hasOwnProperty("userProfile") + ) { + projectSeggregate.userProfileMissing.push( + projectWithIncompleteData[count] + ); + } + } + + //update userRoleInformations if userProfile is present in project + if (projectSeggregate.userRoleInformationMissing.length > 0) { + let updateUserRoleInformationInProjects = []; + for ( + let count = 0; + count < projectSeggregate.userRoleInformationMissing.length; + count++ + ) { + let userRoleInformationForProject = + await getUserRoleInformationFromProfile( + projectSeggregate.userRoleInformationMissing[count].userProfile + ); + let updateProjectWithRoleInformation = { + updateOne: { + filter: { + _id: projectSeggregate.userRoleInformationMissing[count]._id, + }, + update: { + $set: { userRoleInformation: userRoleInformationForProject }, + }, + }, + }; + + updateUserRoleInformationInProjects.push( + updateProjectWithRoleInformation + ); + updatedProjectIds.userRoleInformationMissingProjectIds.push( + projectSeggregate.userRoleInformationMissing[count]._id + ); + } + // will create BulkWrite Query to otimize excution + await db + .collection("projects") + .bulkWrite(updateUserRoleInformationInProjects); + } + + // update Projects With Profile and UserRoleInformation if both are missing + if (projectSeggregate.bothDataMissing.length > 0) { + let updateProjectWithProfileAndUserRoleInformation = []; + for ( + let count = 0; + count < projectSeggregate.bothDataMissing.length; + count++ + ) { + let projectIdWithoutUserProfile = + projectSeggregate.bothDataMissing[count]._id; + let userId = projectSeggregate.bothDataMissing[count].userId; + + //call profile api to get user profile + let profile = await profileReadPrivate(userId); + + if (profile.success && profile.data && profile.data.response) { + //get userRoleInformation from Resuable function + let userRoleInformationForProject = + await getUserRoleInformationFromProfile(profile.data.response); + let updateObject = { + updateOne: { + filter: { + _id: projectIdWithoutUserProfile, + }, + update: { + $set: { + userRoleInformation: userRoleInformationForProject, + userProfile: profile.data.response, + }, + }, + }, + }; + updateProjectWithProfileAndUserRoleInformation.push(updateObject); + updatedProjectIds.bothDataMissingProjectIds.push( + projectIdWithoutUserProfile + ); + } else if (!profile.success) { + updatedProjectIds.failedToGetProfileProjectIds.push( + projectIdWithoutUserProfile + ); + } + } + // will create BulkWrite Query to otimize excution + if (updateProjectWithProfileAndUserRoleInformation.length > 0) { + await db + .collection("projects") + .bulkWrite(updateProjectWithProfileAndUserRoleInformation); + } + } + + // Update Project with user Profile if userRoleInformation is present + if (projectSeggregate.userProfileMissing.length > 0) { + let updateProjectWithuUserProfile = []; + for ( + let count = 0; + count < projectSeggregate.userProfileMissing.length; + count++ + ) { + let projectIdWithoutUserProfile = + projectSeggregate.userProfileMissing[count]._id; + let userId = projectSeggregate.userProfileMissing[count].userId; + + //call profile api to get user profile + let profile = await profileReadPrivate(userId); + if (profile.success && profile.data && profile.data.response) { + let userProfile = profile.data.response; + let userRoleInformation = await getUserRoleInformationFromProfile( + userProfile + ); + let bothRoleInformationEqual = _.isEqual( + userRoleInformation, + projectSeggregate.userProfileMissing[count].userRoleInformation + ); + + if (!bothRoleInformationEqual) { + let userRoleInformationkeys = Object.keys( + projectSeggregate.userProfileMissing[count].userRoleInformation + ); + userProfile = _.omit(userProfile, ["userLocations"]); + userProfile.userLocations = []; + for (let i = 0; i < userRoleInformationkeys.length; i++) { + if (userRoleInformationkeys[i].toUpperCase() === "SCHOOL") { + //get school data + let filterData = { + code: projectSeggregate.userProfileMissing[count] + .userRoleInformation[userRoleInformationkeys[i]], + }; + let schoolData = await locationSearch(filterData); + if (schoolData.success) { + userProfile.userLocations.push(...schoolData.data); + } + } else if ( + userRoleInformationkeys[i].toUpperCase() === "ROLE" + ) { + //get RoleInformation + let userRoles = + projectSeggregate.userProfileMissing[ + count + ].userRoleInformation[userRoleInformationkeys[i]].split( + "," + ); + userProfile.profileUserType = new Array(); + for (let j = 0; j < userRoles.length; j++) { + if (userRoles[j].toUpperCase() === "TEACHER") { + // If subRole is teacher + userProfile.profileUserType.push({ + subType: null, + type: "teacher", + }); + } else { + // If subRole is not teacher + userProfile.profileUserType.push({ + subType: userRoles[j].toLowerCase(), + type: "administrator", + }); + } + } + } else { + // get Other RoleInformation data + let filterData = { + id: projectSeggregate.userProfileMissing[count] + .userRoleInformation[userRoleInformationkeys[i]], + }; + let userLocations = await locationSearch(filterData); + if (userLocations.success) { + userProfile.userLocations.push(...userLocations.data); + } + } + } + } + + let updateObject = { + updateOne: { + filter: { + _id: projectIdWithoutUserProfile, + }, + update: { + $set: { + userProfile: userProfile, + }, + }, + }, + }; + + updateProjectWithuUserProfile.push(updateObject); + updatedProjectIds.userProfileMissingProjectIds.push( + projectIdWithoutUserProfile + ); + } else if (!profile.success) { + updatedProjectIds.failedToGetProfileProjectIds.push( + projectIdWithoutUserProfile + ); + } + } + // will create BulkWrite Query to otimize excution + if (updateProjectWithuUserProfile.length > 0) { + await db + .collection("projects") + .bulkWrite(updateProjectWithuUserProfile); + } + } + //write updated project ids to file + fs.writeFile( + `updatedProjectIds.json`, + + JSON.stringify(updatedProjectIds), + + function (err) { + if (err) { + console.error("Crap happens"); + } + } + ); + } + // this function is used to get userRoleInformation from userProfile + function getUserRoleInformationFromProfile(profile) { + let userRoleInformationForProject = {}; + for (let counter = 0; counter < profile.userLocations.length; counter++) { + if (profile.userLocations[counter].type === "school") { + userRoleInformationForProject.school = + profile.userLocations[counter].code; + } else { + userRoleInformationForProject[profile.userLocations[counter].type] = + profile.userLocations[counter].id; + } + } + let Roles = []; + for ( + let counter = 0; + counter < profile.profileUserType.length; + counter++ + ) { + if ( + profile.profileUserType[counter].hasOwnProperty("subType") && + profile.profileUserType[counter].subType !== null + ) { + Roles.push(profile.profileUserType[counter].subType.toUpperCase()); + } else { + Roles.push(profile.profileUserType[counter].type.toUpperCase()); + } + } + userRoleInformationForProject.role = Roles.join(","); + return userRoleInformationForProject; + } + // this function is used to get location data + function locationSearch(filterData) { + return new Promise(async (resolve, reject) => { + try { + let bodyData = {}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = filterData; + const url = userServiceUrl + endPoint; + const options = { + headers: { + "content-type": "application/json", + }, + json: bodyData, + }; + + request.post(url, options, requestCallback); + + let result = { + success: true, + }; + + function requestCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = data.body; + if ( + response.responseCode === "OK" && + response.result && + response.result.response && + response.result.response.length > 0 + ) { + let entityResult = new Array(); + response.result.response.map((entityData) => { + let entity = _.omit(entityData, ["identifier"]); + entityResult.push(entity); + }); + result["data"] = entityResult; + result["count"] = response.result.count; + } else { + result.success = false; + } + } + return resolve(result); + } + + setTimeout(function () { + return resolve( + (result = { + success: false, + }) + ); + }, 5000); + } catch (error) { + return reject(error); + } + }); + } + //this function to get the user profileData from learn service + + function profileReadPrivate(userId) { + return new Promise(async (resolve, reject) => { + try { + // <--- Important : This url endpoint is private do not use it for regular workflows ---> + let url = ""; + + let url = userServiceUrl + userReadEndpoint + "/" + userId; + const options = { + headers: { + "content-type": "application/json", + }, + }; + request.get(url, options, userReadCallback); + let result = { + success: true, + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = JSON.parse(data.body); + if (response.responseCode === "OK") { + result["data"] = response.result; + } else { + result.success = false; + } + } + return resolve(result); + } + } catch (error) { + return reject(error); + } + }); + } + + console.log("Updated Project Count : ", updatedProjectIds.length); + console.log("completed"); + connection.close(); + } catch (error) { + console.log(error); + } +})().catch((err) => console.error(err)); From fa1cb2a77c4c2b700456899cd8c2b149a2fdd679 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 7 Nov 2023 15:11:48 +0530 Subject: [PATCH 317/373] Added Release Note for 7.0.0 --- release-notes/7.0.0.md | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 release-notes/7.0.0.md diff --git a/release-notes/7.0.0.md b/release-notes/7.0.0.md new file mode 100644 index 00000000..247bd109 --- /dev/null +++ b/release-notes/7.0.0.md @@ -0,0 +1,49 @@ +# Release Note 7.0.0 ML projects Service + +This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Projects service code to 7.0.0. Please consider the following list of tasks to be completed. + +### Deploy ml-projects-services + +To retrieve the latest release tag for version 7.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-7.0.0_RC1 + +To proceed with the deployment process, follow the steps below: + + 1. Log in to Jenkins. + 2. Navigate to Dashboard -> AutoBuild -> StagingManual -> managed-learn -> ml-projects-service. OR for dev Navigate to Dashboard -> Build -> managed-learn -> ml-projects-service + 3. Click on "Build with parameters" and provide the latest release tag in the field labeled "github_release_tag". Initiate the build process. + 4. The build job will take approximately 5 minutes to complete. + 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-projects-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-projects-service This job will be executed automatically in the dev environment. If not, then it should be built manually. + 6. Click on "Build with parameters" to initiate the deployment process. + 7. Once the job is completed, the services will be deployed on the staging environment + +## Migrations + +In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. + +### Update District Name + +This script is designed to update project documents specifically for cases where there is a mismatch in district names. It will only affect the IDs specified in the script. + +#### Step 1: + + Navigate to /opt/projects/updateDistrictNameInProjects/ + +#### Step 2: + +Run the script to update projects. + + node updateDistrictName.js + +### Update Project Documents + +This script will update projects in cases where the user profile is missing and there is a mismatch between userProfile and userRoleInformations. + +### Step 1: + + Navigate to /opt/projects/updateUserProfileAndMissMatchOfRoleInformation/ + +### Step 2: + +Run the script to update projects. + + node updateProjectWithProfileData.js From dfe88311e24758abd3eb4a586c2e3ccd2b24111d Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 10 Nov 2023 10:13:40 +0530 Subject: [PATCH 318/373] Saving Changes to resolve other PR comments --- config/kafka.js | 31 +- generics/helpers/utils.js | 549 +++++++++++++++------------- generics/kafka/consumers/userDMS.js | 22 +- generics/kafka/producers.js | 28 +- generics/services/users.js | 417 +++++++++++---------- module/userProjects/helper.js | 4 +- package.json | 2 +- 7 files changed, 588 insertions(+), 465 deletions(-) diff --git a/config/kafka.js b/config/kafka.js index ad94f0d7..9d6baca7 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -19,6 +19,7 @@ const USER_DELETE_TOPIC = process.env.USER_DELETE_TOPIC; const connect = function () { const Producer = kafka.Producer; KeyedMessage = kafka.KeyedMessage; + const Consumer = kafka.Consumer; const client = new kafka.KafkaClient({ kafkaHost: process.env.KAFKA_URL, @@ -43,7 +44,27 @@ const connect = function () { // project certificate details consumer _sendToKafkaConsumers(CERTIFICATE_TOPIC, process.env.KAFKA_URL); - _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL); + const topics = [{ topic: process.env.USER_DELETE_TOPIC }]; + + const options = { + autoCommit: true, + }; + + const consumer = new Consumer(client, topics, options); + + consumer.on("message", function (message) { + console.log("-------Kafka consumer log starts here------------------"); + console.log("Topic Name: ", USER_DELETE_TOPIC); + console.log("Message: ", JSON.stringify(message)); + console.log("-------Kafka consumer log ends here------------------"); + + userDMSConsumer.messageReceived(message); + }); + + consumer.on("error", function (err) { + userDMSConsumer.errorTriggered(err); + }); + return { kafkaProducer: producer, kafkaClient: client, @@ -82,11 +103,6 @@ var _sendToKafkaConsumers = function (topic, host) { if (message && message.topic === CERTIFICATE_TOPIC) { projectCertificateConsumer.messageReceived(message); } - - //call userDMSConsumer - if (message && message.topic === USER_DELETE_TOPIC) { - userDMSConsumer.messageReceived(message); - } }); consumer.on("error", async function (error) { @@ -96,9 +112,6 @@ var _sendToKafkaConsumers = function (topic, host) { if (error.topics && error.topics[0] === CERTIFICATE_TOPIC) { projectCertificateConsumer.errorTriggered(error); } - if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { - userDMSConsumer.errorTriggered(error); - } }); } }; diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 900d00e3..86da9c4b 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -3,16 +3,18 @@ * author : Aman Karki * Date : 13-July-2020 * Description : All utility functions. -*/ + */ // Dependencies -const {validate : uuidValidate,v4 : uuidV4} = require('uuid'); +const { validate: uuidValidate, v4: uuidV4 } = require("uuid"); +const packageData = require(PROJECT_ROOT_DIRECTORY + "/package.json"); + /** - * convert camel case to title case. - * @function - * @name camelCaseToTitleCase - * @param {String} in_camelCaseString - String of camel case. - * @returns {String} returns a titleCase string. ex: helloThereMister, o/p: Hello There Mister -*/ + * convert camel case to title case. + * @function + * @name camelCaseToTitleCase + * @param {String} in_camelCaseString - String of camel case. + * @returns {String} returns a titleCase string. ex: helloThereMister, o/p: Hello There Mister + */ function camelCaseToTitleCase(in_camelCaseString) { var result = in_camelCaseString // "ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D" @@ -35,135 +37,141 @@ function camelCaseToTitleCase(in_camelCaseString) { return result.charAt(0).toUpperCase() + result.slice(1); } - /** - * Convert hyphen case string to camelCase. - * @function - * @name hyphenCaseToCamelCase - * @param {String} string - String in hyphen case. - * @returns {String} returns a camelCase string. -*/ +/** + * Convert hyphen case string to camelCase. + * @function + * @name hyphenCaseToCamelCase + * @param {String} string - String in hyphen case. + * @returns {String} returns a camelCase string. + */ function hyphenCaseToCamelCase(string) { - return string.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); + return string.replace(/-([a-z])/g, function (g) { + return g[1].toUpperCase(); + }); } - /** - * convert string to lowerCase. - * @function - * @name lowerCase - * @param {String} str - * @returns {String} returns a lowercase string. ex: HELLO, o/p: hello -*/ +/** + * convert string to lowerCase. + * @function + * @name lowerCase + * @param {String} str + * @returns {String} returns a lowercase string. ex: HELLO, o/p: hello + */ function lowerCase(str) { - return str.toLowerCase() + return str.toLowerCase(); } - /** - * check whether the given string is url. - * @function - * @name checkIfStringIsUrl - check whether string is url or not. - * @param {String} str - * @returns {Boolean} returns a Boolean value. ex:"http://example.com:3000/pathname/?search=test" , o/p:true -*/ +/** + * check whether the given string is url. + * @function + * @name checkIfStringIsUrl - check whether string is url or not. + * @param {String} str + * @returns {Boolean} returns a Boolean value. ex:"http://example.com:3000/pathname/?search=test" , o/p:true + */ function checkIfStringIsUrl(str) { - var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol - '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name - '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address - '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path - '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string - '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator + var pattern = new RegExp( + "^(https?:\\/\\/)?" + // protocol + "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|" + // domain name + "((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address + "(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path + "(\\?[;&a-z\\d%_.~+=-]*)?" + // query string + "(\\#[-a-z\\d_]*)?$", + "i" + ); // fragment locator return pattern.test(str); } - /** - * Parse a single column. - * @function - * @name valueParser - Parse value - * @param {String} dataToBeParsed - data to be parsed. - * @returns {Object} returns parsed data -*/ +/** + * Parse a single column. + * @function + * @name valueParser - Parse value + * @param {String} dataToBeParsed - data to be parsed. + * @returns {Object} returns parsed data + */ function valueParser(dataToBeParsed) { + let parsedData = {}; - let parsedData = {} - - Object.keys(dataToBeParsed).forEach(eachDataToBeParsed => { - parsedData[eachDataToBeParsed] = dataToBeParsed[eachDataToBeParsed].trim() - }) + Object.keys(dataToBeParsed).forEach((eachDataToBeParsed) => { + parsedData[eachDataToBeParsed] = dataToBeParsed[eachDataToBeParsed].trim(); + }); - if(parsedData._arrayFields && parsedData._arrayFields.split(",").length > 0) { - parsedData._arrayFields.split(",").forEach(arrayTypeField => { + if ( + parsedData._arrayFields && + parsedData._arrayFields.split(",").length > 0 + ) { + parsedData._arrayFields.split(",").forEach((arrayTypeField) => { if (parsedData[arrayTypeField]) { - parsedData[arrayTypeField] = parsedData[arrayTypeField].split(",") + parsedData[arrayTypeField] = parsedData[arrayTypeField].split(","); } - }) + }); } - return parsedData + return parsedData; } /** - * Convert string to boolean. - * @method - * @name convertStringToBoolean - * @param {String} stringData -String data. - * @returns {Boolean} - Boolean data. - */ - - function convertStringToBoolean(stringData) { - let stringToBoolean = (stringData === "TRUE" || stringData === "true" || stringData === true ); - return stringToBoolean; - } - - /** - * List of boolean data from a given model. - * @method - * @name getAllBooleanDataFromModels - * @param schema - schema - * @returns {Array} Boolean data. - */ - - function getAllBooleanDataFromModels(schema) { - - let defaultSchema = Object.keys(schema); - - let booleanValues = []; - - defaultSchema.forEach(singleSchemaKey=>{ - - let currentSchema = schema[singleSchemaKey]; - - if( - currentSchema.hasOwnProperty('default') && - typeof currentSchema.default === "boolean" - ) { - booleanValues.push(singleSchemaKey); - } - }); + * Convert string to boolean. + * @method + * @name convertStringToBoolean + * @param {String} stringData -String data. + * @returns {Boolean} - Boolean data. + */ + +function convertStringToBoolean(stringData) { + let stringToBoolean = + stringData === "TRUE" || stringData === "true" || stringData === true; + return stringToBoolean; +} - return booleanValues; - } +/** + * List of boolean data from a given model. + * @method + * @name getAllBooleanDataFromModels + * @param schema - schema + * @returns {Array} Boolean data. + */ + +function getAllBooleanDataFromModels(schema) { + let defaultSchema = Object.keys(schema); + + let booleanValues = []; + + defaultSchema.forEach((singleSchemaKey) => { + let currentSchema = schema[singleSchemaKey]; + + if ( + currentSchema.hasOwnProperty("default") && + typeof currentSchema.default === "boolean" + ) { + booleanValues.push(singleSchemaKey); + } + }); - /** - * check whether id is mongodbId or not. - * @function - * @name isValidMongoId - * @param {String} id - * @returns {Boolean} returns whether id is valid mongodb id or not. - */ + return booleanValues; +} - function isValidMongoId(id) { - return ObjectId.isValid(id) && new ObjectId(id).toString() === id; - } +/** + * check whether id is mongodbId or not. + * @function + * @name isValidMongoId + * @param {String} id + * @returns {Boolean} returns whether id is valid mongodb id or not. + */ + +function isValidMongoId(id) { + return ObjectId.isValid(id) && new ObjectId(id).toString() === id; +} - /** - * Get epoch time from current date. - * @function - * @name epochTime - * @returns {Date} returns epoch time. - */ +/** + * Get epoch time from current date. + * @function + * @name epochTime + * @returns {Date} returns epoch time. + */ function epochTime() { var currentDate = new Date(); @@ -172,158 +180,152 @@ function epochTime() { } /** - * Convert Project Status - * @function - * @name convertProjectStatus - * @returns {String} returns converted project status - */ + * Convert Project Status + * @function + * @name convertProjectStatus + * @returns {String} returns converted project status + */ function convertProjectStatus(status) { + let convertedStatus; - let convertedStatus; - - if ( status == CONSTANTS.common.NOT_STARTED_STATUS ) { - convertedStatus = CONSTANTS.common.STARTED; - } else if ( status == CONSTANTS.common.COMPLETED_STATUS ) { - convertedStatus = CONSTANTS.common.SUBMITTED_STATUS; - } else { - convertedStatus = status; - } - - return convertedStatus; + if (status == CONSTANTS.common.NOT_STARTED_STATUS) { + convertedStatus = CONSTANTS.common.STARTED; + } else if (status == CONSTANTS.common.COMPLETED_STATUS) { + convertedStatus = CONSTANTS.common.SUBMITTED_STATUS; + } else { + convertedStatus = status; + } + + return convertedStatus; } /** - * Revert Project Status For Older App - * @function - * @name revertProjectStatus - * @returns {String} returns reverted project status - */ - - function revertProjectStatus(status) { + * Revert Project Status For Older App + * @function + * @name revertProjectStatus + * @returns {String} returns reverted project status + */ +function revertProjectStatus(status) { let revertedStatus; - if ( status == CONSTANTS.common.STARTED ) { - revertedStatus = CONSTANTS.common.NOT_STARTED_STATUS; - } else if ( status == CONSTANTS.common.SUBMITTED_STATUS ) { - revertedStatus = CONSTANTS.common.COMPLETED_STATUS; + if (status == CONSTANTS.common.STARTED) { + revertedStatus = CONSTANTS.common.NOT_STARTED_STATUS; + } else if (status == CONSTANTS.common.SUBMITTED_STATUS) { + revertedStatus = CONSTANTS.common.COMPLETED_STATUS; } else { - revertedStatus = status; - } + revertedStatus = status; + } return revertedStatus; } /** - * revert status or not - * @method - * @name revertStatusorNot - * @param {String} appVersion - app Version. - * @returns {Boolean} - true or false -*/ - -function revertStatusorNot( appVersion ) { - - let versions = ["4.10", "4.11", "4.12" ]; - - let appVer = appVersion.split('.',2).join('.'); - if ( versions.includes(appVer)) { - return false + * revert status or not + * @method + * @name revertStatusorNot + * @param {String} appVersion - app Version. + * @returns {Boolean} - true or false + */ + +function revertStatusorNot(appVersion) { + let versions = ["4.10", "4.11", "4.12"]; + + let appVer = appVersion.split(".", 2).join("."); + if (versions.includes(appVer)) { + return false; } else { - - let appVersionNo = Number(appVer); - if ( !isNaN(appVersionNo) && appVersionNo < 4.7 ) { - return true - } else { - return false - } + let appVersionNo = Number(appVer); + if (!isNaN(appVersionNo) && appVersionNo < 4.7) { + return true; + } else { + return false; + } } - } /** - * check whether string is valid uuid. - * @function - * @name checkValidUUID - * @param {String} uuids - * @returns {Boolean} returns a Boolean value true/false -*/ + * check whether string is valid uuid. + * @function + * @name checkValidUUID + * @param {String} uuids + * @returns {Boolean} returns a Boolean value true/false + */ function checkValidUUID(uuids) { - var validateUUID = true; - if(Array.isArray(uuids)){ - for (var i = 0; uuids.length > i; i++) { - if(!uuidValidate(uuids[i])){ - validateUUID = false - } + if (Array.isArray(uuids)) { + for (var i = 0; uuids.length > i; i++) { + if (!uuidValidate(uuids[i])) { + validateUUID = false; } - }else { - validateUUID = uuidValidate(uuids); + } + } else { + validateUUID = uuidValidate(uuids); } return validateUUID; } /** - * make dates comparable - * @function - * @name createComparableDates - * @param {String} dateArg1 - * @param {String} dateArg2 - * @returns {Object} - date object -*/ + * make dates comparable + * @function + * @name createComparableDates + * @param {String} dateArg1 + * @param {String} dateArg2 + * @returns {Object} - date object + */ function createComparableDates(dateArg1, dateArg2) { - let date1 - if(typeof dateArg1 === "string") { - date1 = new Date(dateArg1.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")) + let date1; + if (typeof dateArg1 === "string") { + date1 = new Date(dateArg1.replace(/(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")); } else { - date1 = new Date(dateArg1) + date1 = new Date(dateArg1); } - - let date2 - if(typeof dateArg2 === "string") { - date2 = new Date(dateArg2.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")) + + let date2; + if (typeof dateArg2 === "string") { + date2 = new Date(dateArg2.replace(/(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")); } else { - date2 = new Date(dateArg2) + date2 = new Date(dateArg2); } - date1.setHours(0) - date1.setMinutes(0) - date1.setSeconds(0) - date2.setHours(0) - date2.setMinutes(0) - date2.setSeconds(0) - return({ + date1.setHours(0); + date1.setMinutes(0); + date1.setSeconds(0); + date2.setHours(0); + date2.setMinutes(0); + date2.setSeconds(0); + return { dateOne: date1, - dateTwo: date2 - }) + dateTwo: date2, + }; } /** - * count attachments - * @function - * @name noOfElementsInArray - * @param {Object} data - data to count - * @param {Object} filter - filter data - * @returns {Number} - attachment count -*/ + * count attachments + * @function + * @name noOfElementsInArray + * @param {Object} data - data to count + * @param {Object} filter - filter data + * @returns {Number} - attachment count + */ function noOfElementsInArray(data, filter = {}) { - if ( !filter || !Object.keys(filter).length > 0 ) { + if (!filter || !Object.keys(filter).length > 0) { return data.length; } - if ( !data.length > 0 ) { + if (!data.length > 0) { return 0; } else { - if ( filter.value == "all" ){ + if (filter.value == "all") { return data.length; } else { let count = 0; - for ( let attachment = 0; attachment < data.length; attachment++ ) { - if ( data[attachment][filter.key] == filter.value ) { - count++ + for (let attachment = 0; attachment < data.length; attachment++) { + if (data[attachment][filter.key] == filter.value) { + count++; } } return count; @@ -332,49 +334,92 @@ function noOfElementsInArray(data, filter = {}) { } /** - * validate lhs and rhs using operator passed as String/ Number - * @function - * @name operatorValidation - * @param {Number or String} valueLhs - * @param {Number or String} valueRhs - * @returns {Boolean} - validation result -*/ + * validate lhs and rhs using operator passed as String/ Number + * @function + * @name operatorValidation + * @param {Number or String} valueLhs + * @param {Number or String} valueRhs + * @returns {Boolean} - validation result + */ function operatorValidation(valueLhs, valueRhs, operator) { - return new Promise(async (resolve, reject) => { - let result = false; - if (operator == "==" ) { - result = (valueLhs == valueRhs) ? true : false - } else if (operator == "!=" ) { - result = (valueLhs != valueRhs) ? true : false - } else if (operator == ">" ) { - result = (valueLhs > valueRhs) ? true : false - } else if (operator == "<" ) { - result = (valueLhs < valueRhs) ? true : false - } else if (operator == "<=" ) { - result = (valueLhs <= valueRhs) ? true : false - } else if (operator == ">=" ) { - result = (valueLhs >= valueRhs) ? true : false - } - return resolve(result) - }) + return new Promise(async (resolve, reject) => { + let result = false; + if (operator == "==") { + result = valueLhs == valueRhs ? true : false; + } else if (operator == "!=") { + result = valueLhs != valueRhs ? true : false; + } else if (operator == ">") { + result = valueLhs > valueRhs ? true : false; + } else if (operator == "<") { + result = valueLhs < valueRhs ? true : false; + } else if (operator == "<=") { + result = valueLhs <= valueRhs ? true : false; + } else if (operator == ">=") { + result = valueLhs >= valueRhs ? true : false; + } + return resolve(result); + }); +} +function getTelemetryEvent(message) { + let telemetryEvent = { + eid: "AUDIT", + ets: epochTime(), + ver: "3.0", + mid: generateUUId(), + actor: { id: message.edata.userId, type: "User" }, + context: { + channel: "0135261634806579203", + pdata: { + id: process.env.ID, + pid: "manage-learn", + ver: packageData.version, + }, + env: "User", + cdata: [{ id: generateUUId(), type: "Request" }], + rollup: {}, + }, + object: { + id: message.edata.userId, + type: "User", + }, + edata: { + state: "Delete", + type: "DeleteUserStatus", + props: [ + "{keycloakCredentials:false, userLookUpTable:true, userExternalIdTable:true, userTable:true}", + ], + }, + }; + return telemetryEvent; +} +/** + * generate uuid + * @function + * @name generateUUId + * @returns {String} returns uuid. + */ + +function generateUUId() { + return uuidV4(); } module.exports = { - camelCaseToTitleCase : camelCaseToTitleCase, - lowerCase : lowerCase, - checkIfStringIsUrl : checkIfStringIsUrl, - hyphenCaseToCamelCase : hyphenCaseToCamelCase, - valueParser : valueParser, - convertStringToBoolean : convertStringToBoolean, - getAllBooleanDataFromModels : getAllBooleanDataFromModels, - epochTime : epochTime, - isValidMongoId : isValidMongoId, - convertProjectStatus : convertProjectStatus, - revertProjectStatus:revertProjectStatus, - revertStatusorNot:revertStatusorNot, - checkValidUUID : checkValidUUID, - createComparableDates : createComparableDates, - noOfElementsInArray : noOfElementsInArray, - operatorValidation : operatorValidation + camelCaseToTitleCase: camelCaseToTitleCase, + lowerCase: lowerCase, + checkIfStringIsUrl: checkIfStringIsUrl, + hyphenCaseToCamelCase: hyphenCaseToCamelCase, + valueParser: valueParser, + convertStringToBoolean: convertStringToBoolean, + getAllBooleanDataFromModels: getAllBooleanDataFromModels, + epochTime: epochTime, + isValidMongoId: isValidMongoId, + convertProjectStatus: convertProjectStatus, + revertProjectStatus: revertProjectStatus, + revertStatusorNot: revertStatusorNot, + checkValidUUID: checkValidUUID, + createComparableDates: createComparableDates, + noOfElementsInArray: noOfElementsInArray, + operatorValidation: operatorValidation, + getTelemetryEvent: getTelemetryEvent, }; diff --git a/generics/kafka/consumers/userDMS.js b/generics/kafka/consumers/userDMS.js index 4c20e74a..c7488e09 100644 --- a/generics/kafka/consumers/userDMS.js +++ b/generics/kafka/consumers/userDMS.js @@ -7,7 +7,7 @@ //dependencies const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); - +const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); /** * submission consumer message received. * @function @@ -22,7 +22,25 @@ var messageReceived = function (message) { // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. let parsedMessage = JSON.parse(message.value); if (parsedMessage.edata.action === "delete-user") { - await userProjectsHelper.userDelete(parsedMessage); + let userDataDeleteStatus = await userProjectsHelper.userDelete( + parsedMessage + ); + if (userDataDeleteStatus.success === true) { + let msgData = await UTILS.getTelemetryEvent(parsedMessage); + let telemetryEvent = { + timestamp: new Date(), + msg: JSON.stringify(msgData), + lname: "TelemetryEventLogger", + tname: "", + level: "INFO", + HOSTNAME: "", + "application.home": "", + }; + await kafkaProducersHelper.pushTelemetryEventToKafka(telemetryEvent); + return resolve("Message Processed."); + } else { + return resolve("Message Processed."); + } } // return resolve("Message Received"); } catch (error) { diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index 269687f1..e23f7124 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -16,7 +16,9 @@ const projectSubmissionTopic = process.env.PROJECT_SUBMISSION_TOPIC != "OFF" ? process.env.PROJECT_SUBMISSION_TOPIC : "sl-improvement-project-submission-dev"; - +const telemetryEventTopic = process.env.TELEMETRY_TOPIC + ? process.env.TELEMETRY_TOPIC + : "sl-telemetry-dev"; const userDeleteTopic = process.env.USER_DELETE_TOPIC; /** @@ -42,6 +44,29 @@ const pushProjectToKafka = function (message) { } }); }; + +/** + * Push message to telemetry. + * @function + * @name pushTelemetryEventToKafka + * @param {Object} message - Message data. + */ +const pushTelemetryEventToKafka = function (message) { + return new Promise(async (resolve, reject) => { + try { + let kafkaPushStatus = await pushMessageToKafka([ + { + topic: telemetryEventTopic, + messages: JSON.stringify(message), + }, + ]); + + return resolve(kafkaPushStatus); + } catch (error) { + return reject(error); + } + }); +}; const pushEventToKafka = function () { return new Promise(async (resolve, reject) => { try { @@ -155,4 +180,5 @@ const pushMessageToKafka = function (payload) { module.exports = { pushProjectToKafka: pushProjectToKafka, pushEventToKafka: pushEventToKafka, + pushTelemetryEventToKafka: pushTelemetryEventToKafka, }; diff --git a/generics/services/users.js b/generics/services/users.js index 57c00fdf..48b05fc2 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -6,227 +6,246 @@ */ //dependencies -const request = require('request'); +const request = require("request"); const userServiceUrl = process.env.USER_SERVICE_URL; -const profile = function ( token,userId = "" ) { - return new Promise(async (resolve, reject) => { - try { - - let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_V5; - - if( userId !== "" ) { - url = url + "/" + userId + "?" + "fields=organisations,roles,locations,declarations,externalIds" - } +const profile = function (token, userId = "") { + return new Promise(async (resolve, reject) => { + try { + let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_V5; + + if (userId !== "") { + url = + url + + "/" + + userId + + "?" + + "fields=organisations,roles,locations,declarations,externalIds"; + } - const options = { - headers : { - "content-type": "application/json", - "x-authenticated-user-token" : token - } - }; - - request.get(url,options,userReadCallback); - let result = { - success : true - }; - function userReadCallback(err, data) { - - if (err) { - result.success = false; - } else { - - let response = JSON.parse(data.body); - if( response.responseCode === HTTP_STATUS_CODE['ok'].code ) { - result["data"] = response.result; - } else { - result.success = false; - } - - } - - return resolve(result); - } - setTimeout(function () { - return resolve (result = { - success : false - }); - }, CONSTANTS.common.SERVER_TIME_OUT); - - } catch (error) { - return reject(error); + const options = { + headers: { + "content-type": "application/json", + "x-authenticated-user-token": token, + }, + }; + + request.get(url, options, userReadCallback); + let result = { + success: true, + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = JSON.parse(data.body); + if (response.responseCode === HTTP_STATUS_CODE["ok"].code) { + result["data"] = response.result; + result.data = _.omit(response.result, [ + "response.email", + "response.maskedEmail", + "response.maskedPhone", + "response.recoveryEmail", + "response.phone", + "response.lastName", + "response.prevUsedPhone", + "response.prevUsedEmail", + "response.recoveryPhone", + ]); + } else { + result.success = false; + } } - }) -} + return resolve(result); + } + setTimeout(function () { + return resolve( + (result = { + success: false, + }) + ); + }, CONSTANTS.common.SERVER_TIME_OUT); + } catch (error) { + return reject(error); + } + }); +}; /** - * - * @function - * @name locationSearch - * @param {object} filterData - location search filter object. - * @param {Boolean} formatResult - format result or not. - * @returns {Promise} returns a promise. -*/ - -const locationSearch = function ( filterData, formatResult = false ) { + * + * @function + * @name locationSearch + * @param {object} filterData - location search filter object. + * @param {Boolean} formatResult - format result or not. + * @returns {Promise} returns a promise. + */ + +const locationSearch = function (filterData, formatResult = false) { return new Promise(async (resolve, reject) => { - try { - - let bodyData={}; - bodyData["request"] = {}; - bodyData["request"]["filters"] = filterData; - const url = - userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; - const options = { - headers : { - "content-type": "application/json" - }, - json : bodyData - }; - - request.post(url,options,requestCallback); - - let result = { - success : true - }; - - function requestCallback(err, data) { - if (err) { - result.success = false; + try { + let bodyData = {}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = filterData; + const url = userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; + const options = { + headers: { + "content-type": "application/json", + }, + json: bodyData, + }; + + request.post(url, options, requestCallback); + + let result = { + success: true, + }; + + function requestCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = data.body; + + if ( + response.responseCode === CONSTANTS.common.OK && + response.result && + response.result.response && + response.result.response.length > 0 + ) { + if (formatResult) { + let entityResult = new Array(); + response.result.response.map((entityData) => { + let data = {}; + data._id = entityData.id; + data.entityType = entityData.type; + data.metaInformation = {}; + data.metaInformation.name = entityData.name; + data.metaInformation.externalId = entityData.code; + data.registryDetails = {}; + data.registryDetails.locationId = entityData.id; + data.registryDetails.code = entityData.code; + entityResult.push(data); + }); + result["data"] = entityResult; + result["count"] = response.result.count; } else { - let response = data.body; - - if( response.responseCode === CONSTANTS.common.OK && - response.result && - response.result.response && - response.result.response.length > 0 - ) { - if ( formatResult ) { - let entityResult =new Array; - response.result.response.map(entityData => { - let data = {}; - data._id = entityData.id; - data.entityType = entityData.type; - data.metaInformation = {}; - data.metaInformation.name = entityData.name; - data.metaInformation.externalId = entityData.code - data.registryDetails = {}; - data.registryDetails.locationId = entityData.id; - data.registryDetails.code = entityData.code; - entityResult.push(data); - }); - result["data"] = entityResult; - result["count"] = response.result.count; - } else { - result["data"] = response.result.response; - result["count"] = response.result.count; - } - - } else { - result.success = false; - } + result["data"] = response.result.response; + result["count"] = response.result.count; } - return resolve(result); + } else { + result.success = false; + } } - - setTimeout(function () { - return resolve (result = { - success : false - }); - }, CONSTANTS.common.SERVER_TIME_OUT); - - } catch (error) { - return reject(error); + return resolve(result); } - }) -} -/** - * get Parent Entities of an entity. - * @method - * @name getParentEntities - * @param {String} entityId - entity id - * @returns {Array} - parent entities. -*/ - -async function getParentEntities( entityId, iteration = 0, parentEntities ) { - if ( iteration == 0 ) { - parentEntities = []; + setTimeout(function () { + return resolve( + (result = { + success: false, + }) + ); + }, CONSTANTS.common.SERVER_TIME_OUT); + } catch (error) { + return reject(error); } + }); +}; +/** + * get Parent Entities of an entity. + * @method + * @name getParentEntities + * @param {String} entityId - entity id + * @returns {Array} - parent entities. + */ - let filterQuery = { - "id" : entityId - }; - - let entityDetails = await locationSearch(filterQuery); - if ( !entityDetails.success ) { - return parentEntities; - } else { - - let entityData = entityDetails.data[0]; - if ( iteration > 0 ) parentEntities.push(entityData); - if ( entityData.parentId ) { - iteration = iteration + 1; - entityId = entityData.parentId; - await getParentEntities(entityId, iteration, parentEntities); - } - } +async function getParentEntities(entityId, iteration = 0, parentEntities) { + if (iteration == 0) { + parentEntities = []; + } + + let filterQuery = { + id: entityId, + }; + let entityDetails = await locationSearch(filterQuery); + if (!entityDetails.success) { return parentEntities; + } else { + let entityData = entityDetails.data[0]; + if (iteration > 0) parentEntities.push(entityData); + if (entityData.parentId) { + iteration = iteration + 1; + entityId = entityData.parentId; + await getParentEntities(entityId, iteration, parentEntities); + } + } + return parentEntities; } /** - * get user profileData without token. - * @method - * @name profileReadPrivate - * @param {String} userId - user Id - * @returns {JSON} - User profile details -*/ + * get user profileData without token. + * @method + * @name profileReadPrivate + * @param {String} userId - user Id + * @returns {JSON} - User profile details + */ const profileReadPrivate = function (userId) { - return new Promise(async (resolve, reject) => { - try { - // <--- Important : This url endpoint is private do not use it for regular workflows ---> - let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_PRIVATE + "/" + userId; - const options = { - headers : { - "content-type": "application/json" - } - }; - request.get(url,options,userReadCallback); - let result = { - success : true - }; - function userReadCallback(err, data) { - if (err) { - result.success = false; - } else { - - let response = JSON.parse(data.body); - if( response.responseCode === HTTP_STATUS_CODE['ok'].code ) { - result["data"] = response.result; - } else { - result.success = false; - } - - } - return resolve(result); - } - setTimeout(function () { - return resolve (result = { - success : false - }); - }, CONSTANTS.common.SERVER_TIME_OUT); - - } catch (error) { - return reject(error); + return new Promise(async (resolve, reject) => { + try { + // <--- Important : This url endpoint is private do not use it for regular workflows ---> + let url = + userServiceUrl + CONSTANTS.endpoints.USER_READ_PRIVATE + "/" + userId; + const options = { + headers: { + "content-type": "application/json", + }, + }; + request.get(url, options, userReadCallback); + let result = { + success: true, + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = JSON.parse(data.body); + if (response.responseCode === HTTP_STATUS_CODE["ok"].code) { + result["data"] = response.result; + result.data = _.omit(response.result, [ + "response.email", + "response.maskedEmail", + "response.maskedPhone", + "response.recoveryEmail", + "response.phone", + "response.lastName", + "response.prevUsedPhone", + "response.prevUsedEmail", + "response.recoveryPhone", + ]); + } else { + result.success = false; + } } - }) -} + return resolve(result); + } + setTimeout(function () { + return resolve( + (result = { + success: false, + }) + ); + }, CONSTANTS.common.SERVER_TIME_OUT); + } catch (error) { + return reject(error); + } + }); +}; module.exports = { - profile : profile, - locationSearch : locationSearch, - getParentEntities : getParentEntities, - profileReadPrivate : profileReadPrivate + profile: profile, + locationSearch: locationSearch, + getParentEntities: getParentEntities, + profileReadPrivate: profileReadPrivate, }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index e2c83371..ab3ac0a9 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -56,9 +56,11 @@ module.exports = class UserProjectsHelper { ["userProfile"], "none" ); + if (userProjectData.length === 0) { + return resolve({ success: false }); + } if (userProjectData.length > 0) { userProjectData.forEach((userProfile) => { - let updatedUserProfile = userProfile.userProfile; let updateProfile = { updateOne: { filter: { _id: userProfile._id }, diff --git a/package.json b/package.json index ab919560..bf152a68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sl-improvement-service", - "version": "1.0.0", + "version": "7.0.0", "description": "Improvement service", "main": "app.js", "bin": { From a6e204e040dc349c66a7ec36d047c94a9f976881 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 10 Nov 2023 10:36:59 +0530 Subject: [PATCH 319/373] Fixing Prod Bug for diksha Issue --- .../updateDistrictNameInProjects/Readme.md | 4 +- .../Readme.md | 4 +- .../updateProjectWithProfileData.js | 8 +-- release-notes/6.0.0.md | 8 +++ release-notes/7.0.0.md | 49 ------------------- 5 files changed, 18 insertions(+), 55 deletions(-) delete mode 100644 release-notes/7.0.0.md diff --git a/migrations/updateDistrictNameInProjects/Readme.md b/migrations/updateDistrictNameInProjects/Readme.md index 09a764f3..e392e2c8 100644 --- a/migrations/updateDistrictNameInProjects/Readme.md +++ b/migrations/updateDistrictNameInProjects/Readme.md @@ -2,13 +2,15 @@ #### Steps to run the script files +This script is intended to address a particular bug in Diksha Prod, and it is unrelated to the 6.0.0 release. + In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. This script is designed to update project documents specifically for cases where there is a mismatch in district names. It will only affect the IDs specified in the script. ### Step 1: - Navigate to /opt/projects/updateDistrictNameInProjects/ + Navigate to /opt/projects/migrations/updateDistrictNameInProjects/ ### Step 2: diff --git a/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md index b73efeeb..346b2337 100644 --- a/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md +++ b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md @@ -2,13 +2,15 @@ #### Steps to run the script files +This script is intended to address a particular bug in Diksha Prod, and it is unrelated to the 6.0.0 release. + In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. This script will update projects in cases where the user profile is missing and there is a mismatch between userProfile and userRoleInformations. ### Step 1: - Navigate to /opt/projects/updateUserProfileAndMissMatchOfRoleInformation/ + Navigate to /opt/projects/migrations/updateUserProfileAndMissMatchOfRoleInformation/ ### Step 2: diff --git a/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js b/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js index 037795f8..3764eec2 100644 --- a/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js +++ b/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js @@ -193,7 +193,7 @@ const userReadEndpoint = "/private/user/v1/read"; // Update Project with user Profile if userRoleInformation is present if (projectSeggregate.userProfileMissing.length > 0) { - let updateProjectWithuUserProfile = []; + let updateProjectWithUserProfile = []; for ( let count = 0; count < projectSeggregate.userProfileMissing.length; @@ -285,7 +285,7 @@ const userReadEndpoint = "/private/user/v1/read"; }, }; - updateProjectWithuUserProfile.push(updateObject); + updateProjectWithUserProfile.push(updateObject); updatedProjectIds.userProfileMissingProjectIds.push( projectIdWithoutUserProfile ); @@ -296,10 +296,10 @@ const userReadEndpoint = "/private/user/v1/read"; } } // will create BulkWrite Query to otimize excution - if (updateProjectWithuUserProfile.length > 0) { + if (updateProjectWithUserProfile.length > 0) { await db .collection("projects") - .bulkWrite(updateProjectWithuUserProfile); + .bulkWrite(updateProjectWithUserProfile); } } //write updated project ids to file diff --git a/release-notes/6.0.0.md b/release-notes/6.0.0.md index 6395cd1b..ba542c2c 100644 --- a/release-notes/6.0.0.md +++ b/release-notes/6.0.0.md @@ -15,3 +15,11 @@ To proceed with the deployment process, follow the steps below: 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-projects-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-projects-service This job will be executed automatically in the dev environment. If not, then it should be built manually. 6. Click on "Build with parameters" to initiate the deployment process. 7. Once the job is completed, the services will be deployed on the staging environment + +## Migrations + +For this release, we haven't included any migrations specifically for the 6.0.0 release. However, we have included two scripts to address a bug in Diksha Prod, and it's important to note that these scripts are not related to the 6.0.0 release. You can find these scripts in the release documentation. + +Script 1 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateDistrictNameInProjects/Readme.md) + +Script 1 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md) diff --git a/release-notes/7.0.0.md b/release-notes/7.0.0.md deleted file mode 100644 index 247bd109..00000000 --- a/release-notes/7.0.0.md +++ /dev/null @@ -1,49 +0,0 @@ -# Release Note 7.0.0 ML projects Service - -This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Projects service code to 7.0.0. Please consider the following list of tasks to be completed. - -### Deploy ml-projects-services - -To retrieve the latest release tag for version 7.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-7.0.0_RC1 - -To proceed with the deployment process, follow the steps below: - - 1. Log in to Jenkins. - 2. Navigate to Dashboard -> AutoBuild -> StagingManual -> managed-learn -> ml-projects-service. OR for dev Navigate to Dashboard -> Build -> managed-learn -> ml-projects-service - 3. Click on "Build with parameters" and provide the latest release tag in the field labeled "github_release_tag". Initiate the build process. - 4. The build job will take approximately 5 minutes to complete. - 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-projects-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-projects-service This job will be executed automatically in the dev environment. If not, then it should be built manually. - 6. Click on "Build with parameters" to initiate the deployment process. - 7. Once the job is completed, the services will be deployed on the staging environment - -## Migrations - -In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. - -### Update District Name - -This script is designed to update project documents specifically for cases where there is a mismatch in district names. It will only affect the IDs specified in the script. - -#### Step 1: - - Navigate to /opt/projects/updateDistrictNameInProjects/ - -#### Step 2: - -Run the script to update projects. - - node updateDistrictName.js - -### Update Project Documents - -This script will update projects in cases where the user profile is missing and there is a mismatch between userProfile and userRoleInformations. - -### Step 1: - - Navigate to /opt/projects/updateUserProfileAndMissMatchOfRoleInformation/ - -### Step 2: - -Run the script to update projects. - - node updateProjectWithProfileData.js From 279acc8271fe8c9002ff1ecf76aa7880a709a64e Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 10 Nov 2023 11:01:38 +0530 Subject: [PATCH 320/373] Fixing Diksha Prod Bug --- migrations/updateDistrictNameInProjects/Readme.md | 2 ++ .../updateUserProfileAndMissMatchOfRoleInformation/Readme.md | 2 ++ release-notes/6.0.0.md | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/migrations/updateDistrictNameInProjects/Readme.md b/migrations/updateDistrictNameInProjects/Readme.md index e392e2c8..7af12bcc 100644 --- a/migrations/updateDistrictNameInProjects/Readme.md +++ b/migrations/updateDistrictNameInProjects/Readme.md @@ -4,6 +4,8 @@ This script is intended to address a particular bug in Diksha Prod, and it is unrelated to the 6.0.0 release. +Here is the ticket for this issue:- (Click Here)[https://project-sunbird.atlassian.net/browse/ED-3101]. + In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. This script is designed to update project documents specifically for cases where there is a mismatch in district names. It will only affect the IDs specified in the script. diff --git a/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md index 346b2337..dee96ecd 100644 --- a/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md +++ b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md @@ -4,6 +4,8 @@ This script is intended to address a particular bug in Diksha Prod, and it is unrelated to the 6.0.0 release. +Here is the ticket for this issue:- (Click Here)[https://project-sunbird.atlassian.net/browse/ED-3101]. + In order to execute this migration script, we need to first log in to the pod where the service is running and then proceed with the provided instructions. This script will update projects in cases where the user profile is missing and there is a mismatch between userProfile and userRoleInformations. diff --git a/release-notes/6.0.0.md b/release-notes/6.0.0.md index ba542c2c..996bc080 100644 --- a/release-notes/6.0.0.md +++ b/release-notes/6.0.0.md @@ -4,7 +4,7 @@ This version contains set of manual activites tasks that must be completed in or ### Deploy ml-projects-services -To retrieve the latest release tag for version 6.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-6.0.0_RC7 +To retrieve the latest release tag for version 6.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-6.0.0_RC8 To proceed with the deployment process, follow the steps below: @@ -20,6 +20,8 @@ To proceed with the deployment process, follow the steps below: For this release, we haven't included any migrations specifically for the 6.0.0 release. However, we have included two scripts to address a bug in Diksha Prod, and it's important to note that these scripts are not related to the 6.0.0 release. You can find these scripts in the release documentation. +Here is the ticket for this issue:- (Click Here)[https://project-sunbird.atlassian.net/browse/ED-3101]. + Script 1 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateDistrictNameInProjects/Readme.md) Script 1 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md) From 2c1abcfe52418649a1415e124825679813a3fcbe Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 14 Nov 2023 09:06:06 +0530 Subject: [PATCH 321/373] Added third script as well --- .../updateDistrictName.js | 9 +- .../updateUserProfileDistrictNameMissing.js | 180 ++++++++++++++++++ .../updateProjectWithProfileData.js | 10 +- 3 files changed, 189 insertions(+), 10 deletions(-) create mode 100644 migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js diff --git a/migrations/updateDistrictNameInProjects/updateDistrictName.js b/migrations/updateDistrictNameInProjects/updateDistrictName.js index 00b10ab1..12ad0a6a 100644 --- a/migrations/updateDistrictNameInProjects/updateDistrictName.js +++ b/migrations/updateDistrictNameInProjects/updateDistrictName.js @@ -1,8 +1,8 @@ /** - * name : updateUserProfileInProjects.js - * author : Priyanka Pradeep + * name : updateDistrictName.js + * author : Ankit Shahu * created-date : 10-Nov-2022 - * Description : Migration script for update userProfile in project + * Description : Update District Name in projects where district name miss matching */ const path = require("path"); @@ -19,8 +19,7 @@ var ObjectId = require("mongodb").ObjectID; var fs = require("fs"); const request = require("request"); -// const userServiceUrl = "http://learner-service:9000"; -const userServiceUrl = "https://staging.sunbirded.org/api/data/"; +const userServiceUrl = "http://learner-service:9000"; const endPoint = "/v1/location/search"; (async () => { diff --git a/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js b/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js new file mode 100644 index 00000000..3aba6c9a --- /dev/null +++ b/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js @@ -0,0 +1,180 @@ +/** + * name : updateUserProfileDistrictNameMissing.js + * author : Ankit Shahu + * created-date : 10-Nov-2023 + * Description : update delhi projects where district name is missing + */ + +const path = require("path"); +let rootPath = path.join(__dirname, "../../"); +require("dotenv").config({ path: rootPath + "/.env" }); + +let _ = require("lodash"); +let mongoUrl = process.env.MONGODB_URL; +let dbName = mongoUrl.split("/").pop(); +let url = mongoUrl.split(dbName)[0]; +var MongoClient = require("mongodb").MongoClient; +var ObjectId = require("mongodb").ObjectID; + +var fs = require("fs"); +const request = require("request"); + +const userServiceUrl = "http://learner-service:9000"; +const userReadEndpoint = "/private/user/v1/read"; +(async () => { + let connection = await MongoClient.connect(url, { useNewUrlParser: true }); + let db = connection.db(dbName); + try { + let updatedProjectIds = []; + let failedToGetProfileProjectIds = []; + + let projectIds = [new ObjectId("6094b974437a217a81589bb5")]; + + //get project information from db + let projectDocuments = await db + .collection("projects") + .find({ + _id: { $in: projectIds }, + }) + .project({ + _id: 1, + userProfile: 1, + userRoleInformation: 1, + userId: 1, + }) + .toArray(); + + // update Projects With Profile and UserRoleInformation if both are missing + if (projectDocuments.length > 0) { + let updateProjectUserRoleAndProfile = []; + for (let count = 0; count < projectDocuments.length; count++) { + let projectId = projectDocuments[count]._id; + let userId = projectDocuments[count].userId; + + //call profile api to get user profile + let profile = await profileReadPrivate(userId); + + if (profile.success && profile.data && profile.data.response) { + //get userRoleInformation from Resuable function + let userDetailsForProject = + await getUserRoleAndProfileWithUpdatedData( + profile.data.response, + projectDocuments[count].userRoleInformation + ); + let updateObject = { + updateOne: { + filter: { + _id: projectId, + }, + update: { + $set: { + userRoleInformation: + userDetailsForProject.userRoleInformation, + userProfile: userDetailsForProject.profile, + }, + }, + }, + }; + updateProjectUserRoleAndProfile.push(updateObject); + updatedProjectIds.push(projectId); + } else if (!profile.success) { + failedToGetProfileProjectIds.push(projectId); + } + } + // will create BulkWrite Query to otimize excution + if (updateProjectUserRoleAndProfile.length > 0) { + await db + .collection("projects") + .bulkWrite(updateProjectUserRoleAndProfile); + } + } + //write updated project ids to file + fs.writeFile( + `updatedProjectIds.json`, + + JSON.stringify({ + updatedProjectIds: updatedProjectIds, + failedToGetProfileProjectIds: failedToGetProfileProjectIds, + }), + + function (err) { + if (err) { + console.error("Crap happens"); + } + } + ); + // this function is used to get userRoleInformation from userProfile + function getUserRoleAndProfileWithUpdatedData( + profile, + userRoleInformation + ) { + for (let counter = 0; counter < profile.userLocations.length; counter++) { + if (profile.userLocations[counter].type === "school") { + userRoleInformation.school = profile.userLocations[counter].code; + } else { + userRoleInformation[profile.userLocations[counter].type] = + profile.userLocations[counter].id; + } + } + if (userRoleInformation.hasOwnProperty("role")) { + //get RoleInformation + let userRoles = userRoleInformation.role.split(","); + profile.profileUserType = new Array(); + for (let j = 0; j < userRoles.length; j++) { + if (userRoles[j].toUpperCase() === "TEACHER") { + // If subRole is teacher + profile.profileUserType.push({ + subType: null, + type: "teacher", + }); + } else { + // If subRole is not teacher + profile.profileUserType.push({ + subType: userRoles[j].toLowerCase(), + type: "administrator", + }); + } + } + } + return { userRoleInformation: userRoleInformation, profile: profile }; + } + + function profileReadPrivate(userId) { + return new Promise(async (resolve, reject) => { + try { + let url = userServiceUrl + userReadEndpoint + "/" + userId; + const options = { + headers: { + "content-type": "application/json", + }, + }; + request.get(url, options, userReadCallback); + let result = { + success: true, + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + let response = JSON.parse(data.body); + if (response.responseCode === "OK") { + result["data"] = response.result; + } else { + result.success = false; + } + } + return resolve(result); + } + } catch (error) { + return reject(error); + } + }); + } + + console.log("Updated Project Count : ", updatedProjectIds.length); + console.log("completed"); + connection.close(); + } catch (error) { + console.log(error); + } +})().catch((err) => console.error(err)); diff --git a/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js b/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js index 3764eec2..a7a572fa 100644 --- a/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js +++ b/migrations/updateUserProfileAndMissMatchOfRoleInformation/updateProjectWithProfileData.js @@ -1,7 +1,7 @@ /** - * name : updateUserProfileInProjects.js - * author : Priyanka Pradeep - * created-date : 10-Nov-2022 + * name : updateProjectWithProfileData.js + * author : Ankit Shahu + * created-date : 10-Nov-2023 * Description : Migration script for update userProfile in project */ @@ -409,8 +409,6 @@ const userReadEndpoint = "/private/user/v1/read"; return new Promise(async (resolve, reject) => { try { // <--- Important : This url endpoint is private do not use it for regular workflows ---> - let url = ""; - let url = userServiceUrl + userReadEndpoint + "/" + userId; const options = { headers: { @@ -447,3 +445,5 @@ const userReadEndpoint = "/private/user/v1/read"; console.log(error); } })().catch((err) => console.error(err)); + +let; From dcb40e16534b8fa19d9407c48c26eba278c1fdf7 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 14 Nov 2023 09:22:18 +0530 Subject: [PATCH 322/373] Added third script as well --- migrations/updateDistrictNameInProjects/Readme.md | 14 ++++++++++++++ .../updateUserProfileDistrictNameMissing.js | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/migrations/updateDistrictNameInProjects/Readme.md b/migrations/updateDistrictNameInProjects/Readme.md index 7af12bcc..842d7aa5 100644 --- a/migrations/updateDistrictNameInProjects/Readme.md +++ b/migrations/updateDistrictNameInProjects/Readme.md @@ -10,6 +10,8 @@ In order to execute this migration script, we need to first log in to the pod wh This script is designed to update project documents specifically for cases where there is a mismatch in district names. It will only affect the IDs specified in the script. +This script is intended to correct inconsistencies in district names within project documents. + ### Step 1: Navigate to /opt/projects/migrations/updateDistrictNameInProjects/ @@ -19,3 +21,15 @@ This script is designed to update project documents specifically for cases where Run the script to update projects. node updateDistrictName.js + +This script is designed to refresh project documents by incorporating the most recent profile information along with the individual's previous role in the project. + +### Step 1: + + Navigate to /opt/projects/migrations/updateDistrictNameInProjects/ + +### Step 2: + +Run the script to update projects. + + node updateUserProfileDistrictNameMissing.js diff --git a/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js b/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js index 3aba6c9a..006a5db1 100644 --- a/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js +++ b/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js @@ -28,7 +28,10 @@ const userReadEndpoint = "/private/user/v1/read"; let updatedProjectIds = []; let failedToGetProfileProjectIds = []; - let projectIds = [new ObjectId("6094b974437a217a81589bb5")]; + let projectIds = [ + new ObjectId("638ef0d0be39f5000813f984"), + new ObjectId("63b3b13d01da8e0008597faa"), + ]; //get project information from db let projectDocuments = await db From 102a61c27fbf4bdda087e7b23a3823d6aae66412 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 15 Nov 2023 06:50:32 +0530 Subject: [PATCH 323/373] Updated Readme file --- release-notes/6.0.0.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/release-notes/6.0.0.md b/release-notes/6.0.0.md index 996bc080..3955eb5d 100644 --- a/release-notes/6.0.0.md +++ b/release-notes/6.0.0.md @@ -18,10 +18,10 @@ To proceed with the deployment process, follow the steps below: ## Migrations -For this release, we haven't included any migrations specifically for the 6.0.0 release. However, we have included two scripts to address a bug in Diksha Prod, and it's important to note that these scripts are not related to the 6.0.0 release. You can find these scripts in the release documentation. +For this release, we haven't included any migrations specifically for the 6.0.0 release. However, we have included three scripts to address a bug in Diksha Prod, and it's important to note that these scripts are not related to the 6.0.0 release. You can find these scripts in the release documentation. Here is the ticket for this issue:- (Click Here)[https://project-sunbird.atlassian.net/browse/ED-3101]. -Script 1 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateDistrictNameInProjects/Readme.md) +Script 1 & 2 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateDistrictNameInProjects/Readme.md) -Script 1 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md) +Script 3 - [Click here](https://github.com/project-sunbird/ml-projects-service/blob/release-6.0.0/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md) From 89840453c38e84ab7b2e6cf6afd3bb27417609b3 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 08:36:54 +0530 Subject: [PATCH 324/373] Done with user delete Flow in projects --- .env.sample | 5 ++ config/kafka.js | 31 +++----- controllers/v1/userProjects.js | 16 ---- databaseQueries/projects.js | 9 ++- generics/constants/common.js | 100 ++++++++++++----------- generics/helpers/utils.js | 30 ++++--- generics/kafka/consumers/userDMS.js | 32 +++----- module/userProjects/helper.js | 119 +++++++++++++++++++++------- release-notes/7.0.0.md | 25 ++++++ 9 files changed, 218 insertions(+), 149 deletions(-) create mode 100644 release-notes/7.0.0.md diff --git a/.env.sample b/.env.sample index 3692dcec..b142119e 100644 --- a/.env.sample +++ b/.env.sample @@ -40,3 +40,8 @@ CERTIFICATE_SERVICE_URL = http://registry-service:8081 PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" // Project certificate enable or disable flag +USER_DELETE_TOPIC = {{env_name}}.delete.user // Topic name for user delete event consumer + +ID = {{env_name}}.sunbird.ml.survey.service // ID of service + +TELEMETRY_TOPIC = {{env_name}}.telemetry.raw // Topic name for telemetry \ No newline at end of file diff --git a/config/kafka.js b/config/kafka.js index 9d6baca7..187b30e4 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -19,7 +19,6 @@ const USER_DELETE_TOPIC = process.env.USER_DELETE_TOPIC; const connect = function () { const Producer = kafka.Producer; KeyedMessage = kafka.KeyedMessage; - const Consumer = kafka.Consumer; const client = new kafka.KafkaClient({ kafkaHost: process.env.KAFKA_URL, @@ -44,26 +43,8 @@ const connect = function () { // project certificate details consumer _sendToKafkaConsumers(CERTIFICATE_TOPIC, process.env.KAFKA_URL); - const topics = [{ topic: process.env.USER_DELETE_TOPIC }]; - - const options = { - autoCommit: true, - }; - - const consumer = new Consumer(client, topics, options); - - consumer.on("message", function (message) { - console.log("-------Kafka consumer log starts here------------------"); - console.log("Topic Name: ", USER_DELETE_TOPIC); - console.log("Message: ", JSON.stringify(message)); - console.log("-------Kafka consumer log ends here------------------"); - - userDMSConsumer.messageReceived(message); - }); - - consumer.on("error", function (err) { - userDMSConsumer.errorTriggered(err); - }); + // user Delete Consumer + _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL); return { kafkaProducer: producer, @@ -103,6 +84,10 @@ var _sendToKafkaConsumers = function (topic, host) { if (message && message.topic === CERTIFICATE_TOPIC) { projectCertificateConsumer.messageReceived(message); } + // call userDelete consumer + if (message && message.topic === USER_DELETE_TOPIC) { + userDMSConsumer.messageReceived(message); + } }); consumer.on("error", async function (error) { @@ -112,8 +97,10 @@ var _sendToKafkaConsumers = function (topic, host) { if (error.topics && error.topics[0] === CERTIFICATE_TOPIC) { projectCertificateConsumer.errorTriggered(error); } + if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { + userDMSConsumer.errorTriggered(error); + } }); } }; - module.exports = connect; diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 46061169..dbd26116 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -157,22 +157,6 @@ module.exports = class UserProjects extends Abstract { }); } - async pushEventInKafka(req) { - return new Promise(async (resolve, reject) => { - try { - let createdProject = await userProjectsHelper.pushEventInKafka(); - - return resolve(createdProject); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } /** * @api {post} /improvement-project/api/v1/userProjects/details/:projectId?programId=:programId&solutionId=:solutionId&templateId=:templateId * Project Details. diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 2740f55e..80712823 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -121,7 +121,14 @@ module.exports = class Projects { }); } - static bulkProfileUpdate(profileData) { + /** + * bulkUpdate function is used to do bulk operations. + * @method + * @name bulkUpdate + * @param {Object} [projectData] - project Data along with filter and quries. + * @returns {Object} - status of bulk operation. + */ + static bulkUpdate(profileData) { return new Promise(async (resolve, reject) => { try { let userProjectProfileUpdate = await database.models.projects.bulkWrite( diff --git a/generics/constants/common.js b/generics/constants/common.js index 30e2703c..c6abbc71 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -6,50 +6,58 @@ */ module.exports = { - "ACTIVE_STATUS" : "active", - "PUBLISHED" : "published", - "SUCCESS" : "Success", - "ASSESSMENT" : "assessment", - "CONTENT" : "content", - "IMPROVEMENT_PROJECT" : "improvementProject", - "MULTIPLE" : "multiple", - "OTHERS" : "Others", - "SIMPLE_TASK_TYPE" : "simple", - "NOT_STARTED" : "not started", - "RECENTLY_ADDED_PROJECT" : "currentlyAdded", - "IMPORTANT_PROJECT" : "importantProject", - "COMPLETED_STATUS" : "completed", - "INPROGRESS_STATUS" : "inProgress", - "NOT_STARTED_STATUS" : "notStarted", - "STARTED":"started", - "SUBMITTED_STATUS":"submitted", - "OBSERVATION" : "observation", - "PUBLISHED_STATUS" : "published", - "LEAD_ASSESSOR" : "LEAD_ASSESSOR", - "PROJECT_DESCRIPTION" : "Manage and track your school improvement easily, by creating tasks and planning project timelines.", - "RESOURCE_TYPE" : "Improvement Project Solution", - "ENGLISH_LANGUAGE" : "English", - "KEYWORDS" : "Improvement Project", - "ASSIGN_TO_ME" : "assignedToMe", - "CREATED_BY_ME" : "createdByMe", - "DEFAULT_PAGE_NO" : 1, - "DEFAULT_PAGE_SIZE" : 100, - "OBSERVATION_REFERENCE_KEY" : "observation", - "ALLOW_MULTIPLE_ASSESSMENTS" : "allowMultipleAssessemts", - "IS_RUBRIC_DRIVEN" : "isRubricDriven", - "CRITERIA_LEVEL_REPORT" : "criteriaLevelReport", - "LINK" : "link", - "DEFAULT_SUBMISSION_REQUIRED" : 1, - "TASK_SEQUENCE" : "taskSequence", - "CHILDREN" : "children", - "ATTACHMENT_TYPE_LINK" : "link", - "PROJECT_ATTACHMENT" : "project", - "TASK_ATTACHMENT" : "task", - "DEFAULT_TASK_COMPLETED" : 0, - "IMAGE_DATA_TYPE" : "image/jpeg", - "DISTRICT": "district", - "SERVER_TIME_OUT" : 5000, - "OK" : "OK", - "PROJECT" : "project", - "PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY" : "Certificate generated successfully" + ACTIVE_STATUS: "active", + PUBLISHED: "published", + SUCCESS: "Success", + ASSESSMENT: "assessment", + CONTENT: "content", + IMPROVEMENT_PROJECT: "improvementProject", + MULTIPLE: "multiple", + OTHERS: "Others", + SIMPLE_TASK_TYPE: "simple", + NOT_STARTED: "not started", + RECENTLY_ADDED_PROJECT: "currentlyAdded", + IMPORTANT_PROJECT: "importantProject", + COMPLETED_STATUS: "completed", + INPROGRESS_STATUS: "inProgress", + NOT_STARTED_STATUS: "notStarted", + STARTED: "started", + SUBMITTED_STATUS: "submitted", + OBSERVATION: "observation", + PUBLISHED_STATUS: "published", + LEAD_ASSESSOR: "LEAD_ASSESSOR", + PROJECT_DESCRIPTION: + "Manage and track your school improvement easily, by creating tasks and planning project timelines.", + RESOURCE_TYPE: "Improvement Project Solution", + ENGLISH_LANGUAGE: "English", + KEYWORDS: "Improvement Project", + ASSIGN_TO_ME: "assignedToMe", + CREATED_BY_ME: "createdByMe", + DEFAULT_PAGE_NO: 1, + DEFAULT_PAGE_SIZE: 100, + OBSERVATION_REFERENCE_KEY: "observation", + ALLOW_MULTIPLE_ASSESSMENTS: "allowMultipleAssessemts", + IS_RUBRIC_DRIVEN: "isRubricDriven", + CRITERIA_LEVEL_REPORT: "criteriaLevelReport", + LINK: "link", + DEFAULT_SUBMISSION_REQUIRED: 1, + TASK_SEQUENCE: "taskSequence", + CHILDREN: "children", + ATTACHMENT_TYPE_LINK: "link", + PROJECT_ATTACHMENT: "project", + TASK_ATTACHMENT: "task", + DEFAULT_TASK_COMPLETED: 0, + IMAGE_DATA_TYPE: "image/jpeg", + DISTRICT: "district", + SERVER_TIME_OUT: 5000, + OK: "OK", + PROJECT: "project", + PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY: + "Certificate generated successfully", + DELETED_USER: "Deleted User", + TELEMTRY_EVENT_LOGGER: "TelemetryEventLogger", + INFO_LEVEL: "INFO", + DELETE_STATE: "Delete", + USER_DELETE_TYPE: "DeleteUserStatus", + AUDIT: "AUDIT", }; diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index 86da9c4b..e8dabee0 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -361,35 +361,33 @@ function operatorValidation(valueLhs, valueRhs, operator) { return resolve(result); }); } -function getTelemetryEvent(message) { + +/** + * generate telemetry raw event + * @function + * @name getTelemetryEvent + * @returns {Object} returns uuid. + */ +function getTelemetryEvent() { let telemetryEvent = { - eid: "AUDIT", + eid: "", ets: epochTime(), ver: "3.0", mid: generateUUId(), - actor: { id: message.edata.userId, type: "User" }, + actor: {}, context: { - channel: "0135261634806579203", + channel: "", pdata: { id: process.env.ID, pid: "manage-learn", ver: packageData.version, }, - env: "User", + env: "", cdata: [{ id: generateUUId(), type: "Request" }], rollup: {}, }, - object: { - id: message.edata.userId, - type: "User", - }, - edata: { - state: "Delete", - type: "DeleteUserStatus", - props: [ - "{keycloakCredentials:false, userLookUpTable:true, userExternalIdTable:true, userTable:true}", - ], - }, + object: {}, + edata: {}, }; return telemetryEvent; } diff --git a/generics/kafka/consumers/userDMS.js b/generics/kafka/consumers/userDMS.js index c7488e09..aeb14ab5 100644 --- a/generics/kafka/consumers/userDMS.js +++ b/generics/kafka/consumers/userDMS.js @@ -1,48 +1,42 @@ /** - * name : projectCertificate.js - * author : Vishnu - * created-date : 10-Oct-2022 - * Description : Project certificates submission consumer. + * name : userDMS.js + * author : Ankit + * created-date : 10-Nov-2023 + * Description : user delete event consumer. */ //dependencies const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); -const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); /** * submission consumer message received. * @function * @name messageReceived - * @param {String} message - consumer data + * @param {Object} message - consumer data + * { + * highWaterOffset:63 + * key:null + * offset:62 + * partition:0 + * topic:'deleteuser' + * value:'{"eid":"BE_JOB_REQUEST","ets":1619527882745,"mid":"LP.1619527882745.32dc378a-430f-49f6-83b5-bd73b767ad36","actor":{"id":"delete-user","type":"System"},"context":{"channel":"01309282781705830427","pdata":{"id":"org.sunbird.platform","ver":"1.0"},"env":"dev"},"object":{"id":"","type":"User"},"edata":{"organisationId":"0126796199493140480","userId":"a102c136-c6da-4c6c-b6b7-0f0681e1aab9","suggested_users":[{"role":"ORG_ADMIN","users":[""]},{"role":"CONTENT_CREATOR","users":[""]},{"role":"COURSE_MENTOR","users":[""]}],"action":"delete-user","iteration":1}}' + * } * @returns {Promise} return a Promise. */ var messageReceived = function (message) { return new Promise(async function (resolve, reject) { try { - // This consumer is consuming from an old topic : PROJECT_CERTIFICATE_TOPIC, which is no more used by data team. ie) using existig topic instead of creating new one. let parsedMessage = JSON.parse(message.value); if (parsedMessage.edata.action === "delete-user") { let userDataDeleteStatus = await userProjectsHelper.userDelete( parsedMessage ); if (userDataDeleteStatus.success === true) { - let msgData = await UTILS.getTelemetryEvent(parsedMessage); - let telemetryEvent = { - timestamp: new Date(), - msg: JSON.stringify(msgData), - lname: "TelemetryEventLogger", - tname: "", - level: "INFO", - HOSTNAME: "", - "application.home": "", - }; - await kafkaProducersHelper.pushTelemetryEventToKafka(telemetryEvent); return resolve("Message Processed."); } else { return resolve("Message Processed."); } } - // return resolve("Message Received"); } catch (error) { return reject(error); } diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index ab3ac0a9..eeac91f8 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -36,6 +36,7 @@ const certificateService = require(GENERICS_FILES_PATH + const certificateValidationsHelper = require(MODULES_BASE_PATH + "/certificateValidations/helper"); const _ = require("lodash"); + const programUsersQueries = require(DB_QUERY_BASE_PATH + "/programUsers"); /** @@ -44,9 +45,63 @@ const programUsersQueries = require(DB_QUERY_BASE_PATH + "/programUsers"); */ module.exports = class UserProjectsHelper { - static userDelete(kafkaEvent) { + /** + * userDelete function to delete users Data. + * @method + * @name userDelete + * @param {userDeleteEvent} - userDeleteEvent message object + * { + "eid": "BE_JOB_REQUEST", + "ets": 1619527882745, + "mid": "LP.1619527882745.32dc378a-430f-49f6-83b5-bd73b767ad36", + "actor": { + "id": "delete-user", + "type": "System" + }, + "context": { + "channel": "01309282781705830427", + "pdata": { + "id": "org.sunbird.platform", + "ver": "1.0" + }, + "env": "dev" + }, + "object": { + "id": "", + "type": "User" + }, + "edata": { + "organisationId": "0126796199493140480", + "userId": "a102c136-c6da-4c6c-b6b7-0f0681e1aab9", + "suggested_users": [ + { + "role": "ORG_ADMIN", + "users": [ + "" + ] + }, + { + "role": "CONTENT_CREATOR", + "users": [ + "" + ] + }, + { + "role": "COURSE_MENTOR", + "users": [ + "" + ] + } + ], + "action": "delete-user", + "iteration": 1 + } + } + * @returns {Promise} success Data. + */ + static userDelete(userDeleteEvent) { return new Promise(async (resolve, reject) => { - let userId = kafkaEvent.edata.userId; + let userId = userDeleteEvent.edata.userId; let userProfileUpdateData = []; let userProjectData = await projectQueries.projectDocument( { @@ -65,7 +120,9 @@ module.exports = class UserProjectsHelper { updateOne: { filter: { _id: userProfile._id }, update: { - $set: { "userProfile.firstName": "deletedUser" }, + $set: { + "userProfile.firstName": CONSTANTS.common.DELETED_USER, + }, $unset: { "userProfile.email": 1, "userProfile.maskedEmail": 1, @@ -84,13 +141,39 @@ module.exports = class UserProjectsHelper { userProfileUpdateData.push(updateProfile); }); } - let updateUserProfile = await projectQueries.bulkProfileUpdate( + let updateUserProfile = await projectQueries.bulkUpdate( userProfileUpdateData ); if (updateUserProfile) { - return resolve({ - success: true, - }); + /** + * Telemetry Raw Event + * {"eid":"","ets":1700188609568,"ver":"3.0","mid":"e55a91cd-7964-46bc-b756-18750787fb32","actor":{},"context":{"channel":"","pdata":{"id":"projectservice","pid":"manage-learn","ver":"7.0.0"},"env":"","cdata":[{"id":"adf3b621-619b-4195-a82d-d814eecdb21f","type":"Request"}],"rollup":{}},"object":{},"edata":{}} + */ + let rawEvent = await UTILS.getTelemetryEvent(); + rawEvent.eid = CONSTANTS.common.AUDIT; + rawEvent.context.channel = userDeleteEvent.context.channel; + rawEvent.context.env = "User"; + rawEvent.edata.state = CONSTANTS.common.DELETE_STATE; + rawEvent.edata.type = CONSTANTS.common.USER_DELETE_TYPE; + rawEvent.edata.props = []; + let userObject = { + id: userId, + type: "User", + }; + rawEvent.actor = userObject; + rawEvent.object = userObject; + + let telemetryEvent = { + timestamp: new Date(), + msg: JSON.stringify(rawEvent), + lname: CONSTANTS.common.TELEMTRY_EVENT_LOGGER, + tname: "", + level: CONSTANTS.common.INFO_LEVEL, + HOSTNAME: "", + "application.home": "", + }; + await kafkaProducersHelper.pushTelemetryEventToKafka(telemetryEvent); + return resolve({ success: true }); } }); } @@ -145,28 +228,6 @@ module.exports = class UserProjectsHelper { return mongooseIds; } - static pushEventInKafka() { - return new Promise(async (resolve, reject) => { - try { - // push project details to kafka - await kafkaProducersHelper.pushEventToKafka(); - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, - }); - } - }); - } /** * Sync project. diff --git a/release-notes/7.0.0.md b/release-notes/7.0.0.md new file mode 100644 index 00000000..17ea261d --- /dev/null +++ b/release-notes/7.0.0.md @@ -0,0 +1,25 @@ +# Release Note 7.0.0 ML Survey Service + +This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Survey service code to 7.0.0. Please consider the following list of tasks to be completed. + +### Deploy ml-survey-services + +To retrieve the latest release tag for version 7.0.0, please visit the following URL: https://github.com/project-sunbird/ml-survey-service/tags e.g. release-7.0.0_RC1 + +To proceed with the deployment process, follow the steps below: + + 1. Log in to Jenkins. + 2. Navigate to Dashboard -> AutoBuild -> StagingManual -> managed-learn -> ml-survey-service. OR for dev Navigate to Dashboard -> Build -> managed-learn -> ml-survey-service + 3. Click on "Build with parameters" and provide the latest release tag in the field labeled "github_release_tag". Initiate the build process. + 4. The build job will take approximately 5 minutes to complete. + 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-survey-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-survey-service This job will be executed automatically in the dev environment. If not, then it should be built manually. + 6. Click on "Build with parameters" to initiate the deployment process. + 7. Once the job is completed, the services will be deployed on the staging environment + +### New Environment Keys Added + +We added new environment keys to the DevOps repository [PR LINK] to as required for new features and functionality. For configuration and access to outside services or resources, these keys will be utilised. + +Please note you don't need to deploy the DevOps repo. Once the PR is merged, deploy this service, env variable will automatically add from the DevOps branch. + +In this release, we have introduced four new environment variables. From 77a847525203e04573e488edcf4e38f95bb74188 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 08:40:25 +0530 Subject: [PATCH 325/373] Done with user delete Flow in projects --- databaseQueries/projects.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 80712823..775a29fd 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -128,14 +128,12 @@ module.exports = class Projects { * @param {Object} [projectData] - project Data along with filter and quries. * @returns {Object} - status of bulk operation. */ - static bulkUpdate(profileData) { + static bulkUpdate(Data) { return new Promise(async (resolve, reject) => { try { - let userProjectProfileUpdate = await database.models.projects.bulkWrite( - profileData - ); - if (userProjectProfileUpdate.result.ok) { - return resolve(userProjectProfileUpdate); + let bulkUpdates = await database.models.projects.bulkWrite(Data); + if (bulkUpdates.result.ok) { + return resolve(bulkUpdates); } } catch (error) { return reject(error); From d6448a611d52db22de3530aa1f905750fd90e24c Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 08:42:50 +0530 Subject: [PATCH 326/373] Done with user delete Flow in projects --- generics/kafka/producers.js | 60 ------------------------------------- 1 file changed, 60 deletions(-) diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index e23f7124..02f6345e 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -67,65 +67,6 @@ const pushTelemetryEventToKafka = function (message) { } }); }; -const pushEventToKafka = function () { - return new Promise(async (resolve, reject) => { - try { - let userID = "39c5d6f8-8f62-48e2-8780-3eab65e502e8"; - let orgid = "0126796199493140480"; - let message = { - eid: "BE_JOB_REQUEST", - ets: 1619527882745, - mid: "LP.1619527882745.32dc378a-430f-49f6-83b5-bd73b767ad36", - actor: { - id: "delete-user", - type: "System", - }, - context: { - channel: "01309282781705830427", - pdata: { - id: "org.sunbird.platform", - ver: "1.0", - }, - env: "dev", - }, - object: { - id: "", - type: "User", - }, - edata: { - organisationId: orgid, - userId: userID, - suggested_users: [ - { - role: "ORG_ADMIN", - users: [""], - }, - { - role: "CONTENT_CREATOR", - users: [""], - }, - { - role: "COURSE_MENTOR", - users: [""], - }, - ], - action: "delete-user", - iteration: 1, - }, - }; - let kafkaPushStatus = await pushMessageToKafka([ - { - topic: userDeleteTopic, - messages: JSON.stringify(message), - }, - ]); - - return resolve(kafkaPushStatus); - } catch (error) { - return reject(error); - } - }); -}; /** * Push message to kafka. @@ -179,6 +120,5 @@ const pushMessageToKafka = function (payload) { module.exports = { pushProjectToKafka: pushProjectToKafka, - pushEventToKafka: pushEventToKafka, pushTelemetryEventToKafka: pushTelemetryEventToKafka, }; From fae654c2b2f7c29115ad07b9d0afc8798b80d364 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 08:46:53 +0530 Subject: [PATCH 327/373] Done with user delete Flow in projects --- envVariables.js | 270 ++++++++++++++++++++++++++++-------------------- 1 file changed, 158 insertions(+), 112 deletions(-) diff --git a/envVariables.js b/envVariables.js index 5228d7ef..51625786 100644 --- a/envVariables.js +++ b/envVariables.js @@ -8,159 +8,205 @@ const Log = require("log"); let log = new Log("debug"); let table = require("cli-table"); -const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); +const certificateService = require(GENERICS_FILES_PATH + + "/services/certificate"); let tableData = new table(); let enviromentVariables = { - "APPLICATION_PORT" : { - "message" : "Please specify the value for e.g. 4201", - "optional" : false + APPLICATION_PORT: { + message: "Please specify the value for e.g. 4201", + optional: false, }, - "APPLICATION_ENV" : { - "message" : "Please specify the value for e.g. local/development/qa/production", - "optional" : false + APPLICATION_ENV: { + message: + "Please specify the value for e.g. local/development/qa/production", + optional: false, }, - "MONGODB_URL" : { - "message" : "Required mongodb url", - "optional" : false + MONGODB_URL: { + message: "Required mongodb url", + optional: false, }, - "INTERNAL_ACCESS_TOKEN" : { - "message" : "Required internal access token", - "optional" : false + INTERNAL_ACCESS_TOKEN: { + message: "Required internal access token", + optional: false, }, - "KAFKA_COMMUNICATIONS_ON_OFF" : { - "message" : "Enable/Disable kafka communications", - "optional" : false + KAFKA_COMMUNICATIONS_ON_OFF: { + message: "Enable/Disable kafka communications", + optional: false, }, - "KAFKA_URL" : { - "message" : "Required", - "optional" : false + KAFKA_URL: { + message: "Required", + optional: false, }, - "USER_SERVICE_URL" : { - "message" : "Required user service base url", - "optional" : false + USER_SERVICE_URL: { + message: "Required user service base url", + optional: false, }, - "SERVICE_NAME" : { - "message" : "current service name", - "optional" : true, - "default" : "ml-projects-service" + SERVICE_NAME: { + message: "current service name", + optional: true, + default: "ml-projects-service", }, - "CERTIFICATE_SERVICE_URL" : { - "message" : "certificate service base url", - "optional" : true, - "default" : "http://registry-service:8081", - "requiredIf" : { - "key": "PROJECT_CERTIFICATE_ON_OFF", - "operator" : "EQUALS", - "value" : "ON" - } + CERTIFICATE_SERVICE_URL: { + message: "certificate service base url", + optional: true, + default: "http://registry-service:8081", + requiredIf: { + key: "PROJECT_CERTIFICATE_ON_OFF", + operator: "EQUALS", + value: "ON", + }, }, - "PROJECT_CERTIFICATE_ON_OFF" : { - "message" : "Enable/Disable project certification", - "optional" : false, - "default" : "ON" - } -} + PROJECT_CERTIFICATE_ON_OFF: { + message: "Enable/Disable project certification", + optional: false, + default: "ON", + }, + USER_DELETE_TOPIC: { + message: "Required user delete kafka topic to consume user delete event", + optional: false, + }, + ID: { + message: "Required Service Id for communication with other services", + optional: false, + }, + TELEMETRY_TOPIC: { + message: "Required telemetry topic", + optional: false, + }, +}; let success = true; -module.exports = function() { - Object.keys(enviromentVariables).forEach(eachEnvironmentVariable=>{ - +module.exports = function () { + Object.keys(enviromentVariables).forEach((eachEnvironmentVariable) => { let tableObj = { - [eachEnvironmentVariable] : "PASSED" + [eachEnvironmentVariable]: "PASSED", }; - + let keyCheckPass = true; - let validRequiredIfOperators = ["EQUALS","NOT_EQUALS"] + let validRequiredIfOperators = ["EQUALS", "NOT_EQUALS"]; - if(enviromentVariables[eachEnvironmentVariable].optional === true - && enviromentVariables[eachEnvironmentVariable].requiredIf - && enviromentVariables[eachEnvironmentVariable].requiredIf.key - && enviromentVariables[eachEnvironmentVariable].requiredIf.key != "" - && enviromentVariables[eachEnvironmentVariable].requiredIf.operator - && validRequiredIfOperators.includes(enviromentVariables[eachEnvironmentVariable].requiredIf.operator) - && enviromentVariables[eachEnvironmentVariable].requiredIf.value - && enviromentVariables[eachEnvironmentVariable].requiredIf.value != "") { - switch (enviromentVariables[eachEnvironmentVariable].requiredIf.operator) { - case "EQUALS": - if(process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] === enviromentVariables[eachEnvironmentVariable].requiredIf.value) { - enviromentVariables[eachEnvironmentVariable].optional = false; - } - break; - case "NOT_EQUALS": - if(process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] != enviromentVariables[eachEnvironmentVariable].requiredIf.value) { - enviromentVariables[eachEnvironmentVariable].optional = false; - } - break; - default: - break; - } + if ( + enviromentVariables[eachEnvironmentVariable].optional === true && + enviromentVariables[eachEnvironmentVariable].requiredIf && + enviromentVariables[eachEnvironmentVariable].requiredIf.key && + enviromentVariables[eachEnvironmentVariable].requiredIf.key != "" && + enviromentVariables[eachEnvironmentVariable].requiredIf.operator && + validRequiredIfOperators.includes( + enviromentVariables[eachEnvironmentVariable].requiredIf.operator + ) && + enviromentVariables[eachEnvironmentVariable].requiredIf.value && + enviromentVariables[eachEnvironmentVariable].requiredIf.value != "" + ) { + switch ( + enviromentVariables[eachEnvironmentVariable].requiredIf.operator + ) { + case "EQUALS": + if ( + process.env[ + enviromentVariables[eachEnvironmentVariable].requiredIf.key + ] === enviromentVariables[eachEnvironmentVariable].requiredIf.value + ) { + enviromentVariables[eachEnvironmentVariable].optional = false; + } + break; + case "NOT_EQUALS": + if ( + process.env[ + enviromentVariables[eachEnvironmentVariable].requiredIf.key + ] != enviromentVariables[eachEnvironmentVariable].requiredIf.value + ) { + enviromentVariables[eachEnvironmentVariable].optional = false; + } + break; + default: + break; + } } - - if(enviromentVariables[eachEnvironmentVariable].optional === false) { - if(!(process.env[eachEnvironmentVariable]) - || process.env[eachEnvironmentVariable] == "") { + + if (enviromentVariables[eachEnvironmentVariable].optional === false) { + if ( + !process.env[eachEnvironmentVariable] || + process.env[eachEnvironmentVariable] == "" + ) { success = false; keyCheckPass = false; - } else if (enviromentVariables[eachEnvironmentVariable].possibleValues - && Array.isArray(enviromentVariables[eachEnvironmentVariable].possibleValues) - && enviromentVariables[eachEnvironmentVariable].possibleValues.length > 0) { - if(!enviromentVariables[eachEnvironmentVariable].possibleValues.includes(process.env[eachEnvironmentVariable])) { + } else if ( + enviromentVariables[eachEnvironmentVariable].possibleValues && + Array.isArray( + enviromentVariables[eachEnvironmentVariable].possibleValues + ) && + enviromentVariables[eachEnvironmentVariable].possibleValues.length > 0 + ) { + if ( + !enviromentVariables[eachEnvironmentVariable].possibleValues.includes( + process.env[eachEnvironmentVariable] + ) + ) { success = false; keyCheckPass = false; - enviromentVariables[eachEnvironmentVariable].message += ` Valid values - ${enviromentVariables[eachEnvironmentVariable].possibleValues.join(", ")}` + enviromentVariables[ + eachEnvironmentVariable + ].message += ` Valid values - ${enviromentVariables[ + eachEnvironmentVariable + ].possibleValues.join(", ")}`; } } } - if((!(process.env[eachEnvironmentVariable]) - || process.env[eachEnvironmentVariable] == "") - && enviromentVariables[eachEnvironmentVariable].default - && enviromentVariables[eachEnvironmentVariable].default != "") { - process.env[eachEnvironmentVariable] = enviromentVariables[eachEnvironmentVariable].default; + if ( + (!process.env[eachEnvironmentVariable] || + process.env[eachEnvironmentVariable] == "") && + enviromentVariables[eachEnvironmentVariable].default && + enviromentVariables[eachEnvironmentVariable].default != "" + ) { + process.env[eachEnvironmentVariable] = + enviromentVariables[eachEnvironmentVariable].default; success = true; keyCheckPass = true; } - if(!keyCheckPass) { - if(enviromentVariables[eachEnvironmentVariable].message !== "") { - tableObj[eachEnvironmentVariable] = - enviromentVariables[eachEnvironmentVariable].message; + if (!keyCheckPass) { + if (enviromentVariables[eachEnvironmentVariable].message !== "") { + tableObj[eachEnvironmentVariable] = + enviromentVariables[eachEnvironmentVariable].message; } else { - tableObj[eachEnvironmentVariable] = `FAILED - ${eachEnvironmentVariable} is required`; + tableObj[ + eachEnvironmentVariable + ] = `FAILED - ${eachEnvironmentVariable} is required`; } } tableData.push(tableObj); - }) + }); log.info(tableData.toString()); getKid(); return { - success : success - } -} + success: success, + }; +}; -async function getKid(){ - if ( process.env.PROJECT_CERTIFICATE_ON_OFF === "ON" ) { - // get certificate issuer kid from sunbird-RC - let kidData = await certificateService.getCertificateIssuerKid(); - if( !kidData.success ) { - console.log("failed to get kid value from registry service : ",kidData) - if( process.env.CERTIFICATE_ISSUER_KID && process.env.CERTIFICATE_ISSUER_KID != "" ) { - global.CERTIFICATE_ISSUER_KID = process.env.CERTIFICATE_ISSUER_KID; - } - // console.log("Server stoped . Failed to set certificate issuer Kid value") - // process.exit(); - } else { - console.log("Kid data fetched successfully : ",kidData.data) - global.CERTIFICATE_ISSUER_KID = kidData.data +async function getKid() { + if (process.env.PROJECT_CERTIFICATE_ON_OFF === "ON") { + // get certificate issuer kid from sunbird-RC + let kidData = await certificateService.getCertificateIssuerKid(); + if (!kidData.success) { + console.log("failed to get kid value from registry service : ", kidData); + if ( + process.env.CERTIFICATE_ISSUER_KID && + process.env.CERTIFICATE_ISSUER_KID != "" + ) { + global.CERTIFICATE_ISSUER_KID = process.env.CERTIFICATE_ISSUER_KID; } - console.log(JSON.stringify(kidData)) - // global.CERTIFICATE_ISSUER_KID = kidData.data + // console.log("Server stoped . Failed to set certificate issuer Kid value") + // process.exit(); + } else { + console.log("Kid data fetched successfully : ", kidData.data); + global.CERTIFICATE_ISSUER_KID = kidData.data; + } + console.log(JSON.stringify(kidData)); + // global.CERTIFICATE_ISSUER_KID = kidData.data } -}; - - - +} From 8b1e664f6a67ff12fef0a0f4066b62fb042565bb Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 09:30:29 +0530 Subject: [PATCH 328/373] Done with user delete Flow in projects --- generics/kafka/consumers/userDMS.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generics/kafka/consumers/userDMS.js b/generics/kafka/consumers/userDMS.js index aeb14ab5..7cb78372 100644 --- a/generics/kafka/consumers/userDMS.js +++ b/generics/kafka/consumers/userDMS.js @@ -8,7 +8,7 @@ //dependencies const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); /** - * submission consumer message received. + * consumer message received. * @function * @name messageReceived * @param {Object} message - consumer data From 6395c188726b3d714c63f35b0adde9bd2879007d Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 09:33:50 +0530 Subject: [PATCH 329/373] Added step three in readme file --- migrations/updateDistrictNameInProjects/Readme.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/migrations/updateDistrictNameInProjects/Readme.md b/migrations/updateDistrictNameInProjects/Readme.md index 842d7aa5..ddfe5dde 100644 --- a/migrations/updateDistrictNameInProjects/Readme.md +++ b/migrations/updateDistrictNameInProjects/Readme.md @@ -22,13 +22,9 @@ Run the script to update projects. node updateDistrictName.js -This script is designed to refresh project documents by incorporating the most recent profile information along with the individual's previous role in the project. - -### Step 1: +### Step 3: - Navigate to /opt/projects/migrations/updateDistrictNameInProjects/ - -### Step 2: +This script is designed to refresh project documents by incorporating the most recent profile information along with the individual's previous role in the project. Run the script to update projects. From 83b4885174ef3cafb29d23704306bee9af808b97 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 13:51:21 +0530 Subject: [PATCH 330/373] Done with user delete Flow in projects --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index b142119e..75b84fec 100644 --- a/.env.sample +++ b/.env.sample @@ -42,6 +42,6 @@ PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" USER_DELETE_TOPIC = {{env_name}}.delete.user // Topic name for user delete event consumer -ID = {{env_name}}.sunbird.ml.survey.service // ID of service +ID = {{env_name}}.sunbird.ml.projects.service // ID of service TELEMETRY_TOPIC = {{env_name}}.telemetry.raw // Topic name for telemetry \ No newline at end of file From 2505bb6d11399371417b94ca8a8d728689fc7477 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 14:40:56 +0530 Subject: [PATCH 331/373] Done with user delete Flow in projects --- release-notes/7.0.0.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/release-notes/7.0.0.md b/release-notes/7.0.0.md index 17ea261d..427bb7aa 100644 --- a/release-notes/7.0.0.md +++ b/release-notes/7.0.0.md @@ -1,25 +1,29 @@ -# Release Note 7.0.0 ML Survey Service +# Release Note 7.0.0 ML Projects Service -This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Survey service code to 7.0.0. Please consider the following list of tasks to be completed. +This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Projects service code to 7.0.0. Please consider the following list of tasks to be completed. -### Deploy ml-survey-services +### Deploy ml-projects-services -To retrieve the latest release tag for version 7.0.0, please visit the following URL: https://github.com/project-sunbird/ml-survey-service/tags e.g. release-7.0.0_RC1 +To retrieve the latest release tag for version 7.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-7.0.0_RC1 To proceed with the deployment process, follow the steps below: 1. Log in to Jenkins. - 2. Navigate to Dashboard -> AutoBuild -> StagingManual -> managed-learn -> ml-survey-service. OR for dev Navigate to Dashboard -> Build -> managed-learn -> ml-survey-service + 2. Navigate to Dashboard -> AutoBuild -> StagingManual -> managed-learn -> ml-projects-service. OR for dev Navigate to Dashboard -> Build -> managed-learn -> ml-projects-service 3. Click on "Build with parameters" and provide the latest release tag in the field labeled "github_release_tag". Initiate the build process. 4. The build job will take approximately 5 minutes to complete. - 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-survey-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-survey-service This job will be executed automatically in the dev environment. If not, then it should be built manually. + 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-projects-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-projects-service This job will be executed automatically in the dev environment. If not, then it should be built manually. 6. Click on "Build with parameters" to initiate the deployment process. 7. Once the job is completed, the services will be deployed on the staging environment ### New Environment Keys Added -We added new environment keys to the DevOps repository [PR LINK] to as required for new features and functionality. For configuration and access to outside services or resources, these keys will be utilised. +We added new environment keys to the DevOps repository ([PR link](https://github.com/project-sunbird/sunbird-devops/pull/3921/files)) to as required for new features and functionality. For configuration and access to outside services or resources, these keys will be utilised. Please note you don't need to deploy the DevOps repo. Once the PR is merged, deploy this service, env variable will automatically add from the DevOps branch. In this release, we have introduced four new environment variables. + + USER_DELETE_TOPIC={{user_delete_topic_name | default("")}} + ID={{ml_project_service_id | default("")}} + TELEMETRY_TOPIC={{telemetry_raw_topic_name | default("")}} \ No newline at end of file From f0d25c0bf93c25f289b24aee8cb7da0d38a1c0d1 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 17 Nov 2023 17:31:54 +0530 Subject: [PATCH 332/373] Added validation steps as well --- .../updateDistrictNameInProjects/Readme.md | 52 +++++++++++++ .../updateDistrictName.js | 2 +- .../updateUserProfileDistrictNameMissing.js | 2 +- .../Readme.md | 76 +++++++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) diff --git a/migrations/updateDistrictNameInProjects/Readme.md b/migrations/updateDistrictNameInProjects/Readme.md index ddfe5dde..254502d3 100644 --- a/migrations/updateDistrictNameInProjects/Readme.md +++ b/migrations/updateDistrictNameInProjects/Readme.md @@ -22,6 +22,32 @@ Run the script to update projects. node updateDistrictName.js +#### Validation + +After the script has been executed in the production environment, we can validate the data by utilizing the DBfind API. + +Retrieve the project IDs from `updateDistrictName.json` and include them in the body of the DBfind API request as follows. + +{ + "query": { + "_id": { + "$in": [ + //Add Project Ids here + ] + } + }, + "mongoIdKeys": [ + "_id" + ], + "projection": [ + "userProfile.userLocations" + ], + "limit": 200, + "skip": 0 +} + +After receiving the response, ensure that the userLocations does not include a district named `Gaurela-Pendra-Marvahi` or `Bastar` instead, it should have either `Gourela Pendra Marvahi` and `Baster`. + ### Step 3: This script is designed to refresh project documents by incorporating the most recent profile information along with the individual's previous role in the project. @@ -29,3 +55,29 @@ This script is designed to refresh project documents by incorporating the most r Run the script to update projects. node updateUserProfileDistrictNameMissing.js + +#### Validation + +After the script has been executed in the production environment, we can validate the data by utilizing the DBfind API. + +Retrieve the project IDs from `updateUserProfileDistrictNameMissing.json` and include them in the body of the DBfind API request as follows. + +{ + "query": { + "_id": { + "$in": [ + //Add Project Ids here + ] + } + }, + "mongoIdKeys": [ + "_id" + ], + "projection": [ + "userProfile.userLocations", "userRoleInformation" + ], + "limit": 200, + "skip": 0 +} + +Upon receiving the response from the DBfind API, ensure that `userProfile.userLocations` and `userRoleInformation` contain valid entries for both district names and corresponding IDs. diff --git a/migrations/updateDistrictNameInProjects/updateDistrictName.js b/migrations/updateDistrictNameInProjects/updateDistrictName.js index 12ad0a6a..5daac1a5 100644 --- a/migrations/updateDistrictNameInProjects/updateDistrictName.js +++ b/migrations/updateDistrictNameInProjects/updateDistrictName.js @@ -100,7 +100,7 @@ const endPoint = "/v1/location/search"; await db.collection("projects").bulkWrite(updateProjectDocument); } fs.writeFile( - `updatedProjectIds.json`, + `updateDistrictName.json`, JSON.stringify(updatedProjectIds), diff --git a/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js b/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js index 006a5db1..dfb6a7e8 100644 --- a/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js +++ b/migrations/updateDistrictNameInProjects/updateUserProfileDistrictNameMissing.js @@ -93,7 +93,7 @@ const userReadEndpoint = "/private/user/v1/read"; } //write updated project ids to file fs.writeFile( - `updatedProjectIds.json`, + `updateUserProfileDistrictNameMissing.json`, JSON.stringify({ updatedProjectIds: updatedProjectIds, diff --git a/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md index dee96ecd..826a1b5c 100644 --- a/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md +++ b/migrations/updateUserProfileAndMissMatchOfRoleInformation/Readme.md @@ -19,3 +19,79 @@ This script will update projects in cases where the user profile is missing and Run the script to update projects. node updateProjectWithProfileData.js + +### Setp 3: Validations + +upon executing this script we can validate the data using DBfind api + +#### check for userRoleInformation missing in projects + +Open the `updatedProjectIds.json` file and extract the project IDs from `userRoleInformationMissingProjectIds`. Utilize these project IDs in the following DBfind API to retrieve the corresponding projects. + +{ + "query": { + "_id": { + "$in": [ + // Add project ids here + ] + } + }, + "mongoIdKeys": [ + "_id" + ], + "projection": [ + "userRoleInformation" + ], + "limit": 200, + "skip": 0 +} + +After obtaining the response, validate that all projects include userRoleInformation entries. + +#### check for userProfile missing in projects + +Open the `updatedProjectIds.json` file and extract the project IDs from `userProfileMissingProjectIds`. Utilize these project IDs in the following DBfind API to retrieve the corresponding projects. + +{ + "query": { + "_id": { + "$in": [ + // Add project ids here + ] + } + }, + "mongoIdKeys": [ + "_id" + ], + "projection": [ + "userProfile" + ], + "limit": 200, + "skip": 0 +} + +After obtaining the response, validate that all projects include userProfile entries. + +#### check for userRoleInformation and userProfile missing in projects + +Open the `updatedProjectIds.json` file and extract the project IDs from `bothDataMissingProjectIds`. Utilize these project IDs in the following DBfind API to retrieve the corresponding projects. + +{ + "query": { + "_id": { + "$in": [ + // Add project ids here + ] + } + }, + "mongoIdKeys": [ + "_id" + ], + "projection": [ + "userRoleInformation","userProfile" + ], + "limit": 200, + "skip": 0 +} + +After obtaining the response, validate that all projects include both userRoleInformation and userProfile entries. \ No newline at end of file From 34aa33f4fc01955f8a92163dbd08ba0710ebeb04 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 20 Nov 2023 17:27:17 +0530 Subject: [PATCH 333/373] Updated PR --- .env.sample | 7 +- config/kafka.js | 129 +- databaseQueries/projects.js | 223 +- envVariables.js | 381 +- generics/constants/common.js | 113 +- generics/helpers/utils.js | 538 +- .../consumers/{userDMS.js => userDelete.js} | 4 +- generics/kafka/producers.js | 124 +- generics/services/users.js | 426 +- module/userProjects/helper.js | 7614 ++++++++--------- release-notes/7.0.0.md | 1 + 11 files changed, 4616 insertions(+), 4944 deletions(-) rename generics/kafka/consumers/{userDMS.js => userDelete.js} (92%) diff --git a/.env.sample b/.env.sample index 75b84fec..f92108d3 100644 --- a/.env.sample +++ b/.env.sample @@ -42,6 +42,9 @@ PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" USER_DELETE_TOPIC = {{env_name}}.delete.user // Topic name for user delete event consumer -ID = {{env_name}}.sunbird.ml.projects.service // ID of service +ID = ID = {{env_name}}.{{sunbird_instance}}.ml.core.service // ID of service + +TELEMETRY_ON_OFF = ON/OFF // telemetry service on off + +TELEMETRY_TOPIC = {{env_name}}.telemetry.raw // Topic name for telemetry -TELEMETRY_TOPIC = {{env_name}}.telemetry.raw // Topic name for telemetry \ No newline at end of file diff --git a/config/kafka.js b/config/kafka.js index 187b30e4..57951514 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -3,104 +3,123 @@ * author : Aman Karki * created-date : 08-Sep-2020 * Description : Kafka Configurations related information. - */ +*/ + //dependencies -const kafka = require("kafka-node"); +const kafka = require('kafka-node'); const SUBMISSION_TOPIC = process.env.SUBMISSION_TOPIC; const CERTIFICATE_TOPIC = process.env.PROJECT_SUBMISSION_TOPIC; const USER_DELETE_TOPIC = process.env.USER_DELETE_TOPIC; /** - * Kafka configurations. - * @function - * @name connect - */ - -const connect = function () { - const Producer = kafka.Producer; - KeyedMessage = kafka.KeyedMessage; - - const client = new kafka.KafkaClient({ - kafkaHost: process.env.KAFKA_URL, - }); - - client.on("error", function (error) { - console.log("kafka connection error!"); - }); + * Kafka configurations. + * @function + * @name connect +*/ + +const connect = function() { + + const Producer = kafka.Producer + KeyedMessage = kafka.KeyedMessage + + const client = new kafka.KafkaClient({ + kafkaHost : process.env.KAFKA_URL + }); - const producer = new Producer(client); + client.on('error', function(error) { + console.log("kafka connection error!") + }); - producer.on("ready", function () { - console.log("Connected to Kafka"); - }); + const producer = new Producer(client) - producer.on("error", function (err) { - console.log("kafka producer creation error!"); - }); + producer.on('ready', function () { + console.log("Connected to Kafka"); + }); + + producer.on('error', function (err) { + console.log("kafka producer creation error!") + }) + + _sendToKafkaConsumers( + SUBMISSION_TOPIC, + process.env.KAFKA_URL + ); - _sendToKafkaConsumers(SUBMISSION_TOPIC, process.env.KAFKA_URL); + // project certificate details consumer + _sendToKafkaConsumers( + CERTIFICATE_TOPIC, + process.env.KAFKA_URL + ); - // project certificate details consumer - _sendToKafkaConsumers(CERTIFICATE_TOPIC, process.env.KAFKA_URL); + // user Delete Consumer + _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL); - // user Delete Consumer - _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL); + return { + kafkaProducer: producer, + kafkaClient: client + }; - return { - kafkaProducer: producer, - kafkaClient: client, - }; }; /** - * Send data based on topic to kafka consumers - * @function - * @name _sendToKafkaConsumers - * @param {String} topic - name of kafka topic. - * @param {String} host - kafka host - */ - -var _sendToKafkaConsumers = function (topic, host) { + * Send data based on topic to kafka consumers + * @function + * @name _sendToKafkaConsumers + * @param {String} topic - name of kafka topic. + * @param {String} host - kafka host +*/ + +var _sendToKafkaConsumers = function (topic,host) { + if (topic && topic != "") { + let consumer = new kafka.ConsumerGroup( { - kafkaHost: host, - groupId: process.env.KAFKA_GROUP_ID, - autoCommit: true, - }, - topic - ); + kafkaHost : host, + groupId : process.env.KAFKA_GROUP_ID, + autoCommit : true + },topic + ); + + consumer.on('message', async function (message) { - consumer.on("message", async function (message) { console.log("-------Kafka consumer log starts here------------------"); console.log("Topic Name: ", topic); console.log("Message: ", JSON.stringify(message)); console.log("-------Kafka consumer log ends here------------------"); + if (message && message.topic === SUBMISSION_TOPIC) { submissionsConsumer.messageReceived(message); } - // call projectCertificateConsumer + // call projectCertificateConsumer if (message && message.topic === CERTIFICATE_TOPIC) { projectCertificateConsumer.messageReceived(message); } + // call userDelete consumer if (message && message.topic === USER_DELETE_TOPIC) { - userDMSConsumer.messageReceived(message); + userDeleteConsumer.messageReceived(message); } + }); - consumer.on("error", async function (error) { - if (error.topics && error.topics[0] === SUBMISSION_TOPIC) { + consumer.on('error', async function (error) { + + if(error.topics && error.topics[0] === SUBMISSION_TOPIC) { submissionsConsumer.errorTriggered(error); } - if (error.topics && error.topics[0] === CERTIFICATE_TOPIC) { + if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { projectCertificateConsumer.errorTriggered(error); } + if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { - userDMSConsumer.errorTriggered(error); + userDeleteConsumer.errorTriggered(error); } + }); + } }; + module.exports = connect; diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 775a29fd..2329bd93 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -5,57 +5,62 @@ * Description : Project categories helper for DB interactions. */ -// Dependencies +// Dependencies /** - * Projects - * @class - */ + * Projects + * @class +*/ module.exports = class Projects { - /** - * Lists of projects document. - * @method - * @name projectDocument - * @param {Array} [filterData = "all"] - project filter query. - * @param {Array} [fieldsArray = "all"] - projected fields. - * @param {Array} [skipFields = "none"] - field not to include - * @returns {Array} Lists of projects. - */ - - static projectDocument( - filterData = "all", - fieldsArray = "all", - skipFields = "none" - ) { - return new Promise(async (resolve, reject) => { - try { - let queryObject = filterData != "all" ? filterData : {}; - let projection = {}; - - if (fieldsArray != "all") { - fieldsArray.forEach((field) => { - projection[field] = 1; - }); - } - - if (skipFields !== "none") { - skipFields.forEach((field) => { - projection[field] = 0; - }); - } - - let projects = await database.models.projects - .find(queryObject, projection) - .lean(); - return resolve(projects); - } catch (error) { - return reject(error); - } - }); - } /** + * Lists of projects document. + * @method + * @name projectDocument + * @param {Array} [filterData = "all"] - project filter query. + * @param {Array} [fieldsArray = "all"] - projected fields. + * @param {Array} [skipFields = "none"] - field not to include + * @returns {Array} Lists of projects. + */ + + static projectDocument( + filterData = "all", + fieldsArray = "all", + skipFields = "none" + ) { + return new Promise(async (resolve, reject) => { + try { + + let queryObject = (filterData != "all") ? filterData : {}; + let projection = {} + + if (fieldsArray != "all") { + fieldsArray.forEach(field => { + projection[field] = 1; + }); + } + + if( skipFields !== "none" ) { + skipFields.forEach(field=>{ + projection[field] = 0; + }); + } + + let projects = + await database.models.projects.find( + queryObject, + projection + ).lean(); + return resolve(projects); + + } catch (error) { + return reject(error); + } + }); + } + + /** * Get Aggregate of Project documents. * @method * @name getAggregate @@ -63,20 +68,21 @@ module.exports = class Projects { * @returns {Array} - Project data. */ - static getAggregate(aggregateData) { - return new Promise(async (resolve, reject) => { - try { - let projectDocuments = await database.models.projects.aggregate( - aggregateData - ); - return resolve(projectDocuments); - } catch (error) { - return reject(error); - } - }); - } + static getAggregate(aggregateData) { + return new Promise(async (resolve, reject) => { + + try { + + let projectDocuments = await database.models.projects.aggregate(aggregateData); + return resolve(projectDocuments); - /** + } catch (error) { + return reject(error); + } + }); + } + + /** * Update project documents. * @method * @name findOneAndUpdate @@ -85,22 +91,21 @@ module.exports = class Projects { * @returns {Object} - Project data. */ - static findOneAndUpdate(findQuery, UpdateObject, returnData = {}) { - return new Promise(async (resolve, reject) => { - try { - let projectDocument = await database.models.projects.findOneAndUpdate( - findQuery, - UpdateObject, - returnData - ); - return resolve(projectDocument); - } catch (error) { - return reject(error); - } - }); - } + static findOneAndUpdate(findQuery,UpdateObject, returnData = {}) { + return new Promise(async (resolve, reject) => { + + try { + + let projectDocument = await database.models.projects.findOneAndUpdate(findQuery,UpdateObject, returnData); + return resolve(projectDocument); - /** + } catch (error) { + return reject(error); + } + }); + } + + /** * Create project documents. * @method * @name createProject @@ -108,36 +113,46 @@ module.exports = class Projects { * @returns {Array} - Project data. */ - static createProject(projectData) { - return new Promise(async (resolve, reject) => { - try { - let projectDocument = await database.models.projects.create( - projectData - ); - return resolve(projectDocument); - } catch (error) { - return reject(error); - } - }); - } + static createProject(projectData) { + return new Promise(async (resolve, reject) => { + + try { + + let projectDocument = await database.models.projects.create(projectData); + return resolve(projectDocument); + + } catch (error) { + return reject(error); + } + }); + } + + /** + * Update projects + * @method + * @name updateMany + * @param {Object} query + * @param {Object} update + * @param {Object} options + * @returns {JSON} - update projects. + */ + + static updateMany(query, update, options = {}) { + return new Promise(async (resolve, reject) => { + try { + + let projectsData = await database.models.projects.updateMany( + query, + update, + options + ); + if( projectsData) { + return resolve(projectsData); + } + } catch (error) { + return reject(error); + } + }) + } - /** - * bulkUpdate function is used to do bulk operations. - * @method - * @name bulkUpdate - * @param {Object} [projectData] - project Data along with filter and quries. - * @returns {Object} - status of bulk operation. - */ - static bulkUpdate(Data) { - return new Promise(async (resolve, reject) => { - try { - let bulkUpdates = await database.models.projects.bulkWrite(Data); - if (bulkUpdates.result.ok) { - return resolve(bulkUpdates); - } - } catch (error) { - return reject(error); - } - }); - } }; diff --git a/envVariables.js b/envVariables.js index 51625786..61e64153 100644 --- a/envVariables.js +++ b/envVariables.js @@ -5,208 +5,179 @@ * Description : Required Environment variables . */ -const Log = require("log"); -let log = new Log("debug"); -let table = require("cli-table"); -const certificateService = require(GENERICS_FILES_PATH + - "/services/certificate"); - -let tableData = new table(); - -let enviromentVariables = { - APPLICATION_PORT: { - message: "Please specify the value for e.g. 4201", - optional: false, - }, - APPLICATION_ENV: { - message: - "Please specify the value for e.g. local/development/qa/production", - optional: false, - }, - MONGODB_URL: { - message: "Required mongodb url", - optional: false, - }, - INTERNAL_ACCESS_TOKEN: { - message: "Required internal access token", - optional: false, - }, - KAFKA_COMMUNICATIONS_ON_OFF: { - message: "Enable/Disable kafka communications", - optional: false, - }, - KAFKA_URL: { - message: "Required", - optional: false, - }, - USER_SERVICE_URL: { - message: "Required user service base url", - optional: false, - }, - SERVICE_NAME: { - message: "current service name", - optional: true, - default: "ml-projects-service", - }, - CERTIFICATE_SERVICE_URL: { - message: "certificate service base url", - optional: true, - default: "http://registry-service:8081", - requiredIf: { - key: "PROJECT_CERTIFICATE_ON_OFF", - operator: "EQUALS", - value: "ON", - }, - }, - PROJECT_CERTIFICATE_ON_OFF: { - message: "Enable/Disable project certification", - optional: false, - default: "ON", - }, - USER_DELETE_TOPIC: { - message: "Required user delete kafka topic to consume user delete event", - optional: false, - }, - ID: { - message: "Required Service Id for communication with other services", - optional: false, - }, - TELEMETRY_TOPIC: { - message: "Required telemetry topic", - optional: false, - }, -}; - -let success = true; - -module.exports = function () { - Object.keys(enviromentVariables).forEach((eachEnvironmentVariable) => { - let tableObj = { - [eachEnvironmentVariable]: "PASSED", - }; - - let keyCheckPass = true; - let validRequiredIfOperators = ["EQUALS", "NOT_EQUALS"]; - - if ( - enviromentVariables[eachEnvironmentVariable].optional === true && - enviromentVariables[eachEnvironmentVariable].requiredIf && - enviromentVariables[eachEnvironmentVariable].requiredIf.key && - enviromentVariables[eachEnvironmentVariable].requiredIf.key != "" && - enviromentVariables[eachEnvironmentVariable].requiredIf.operator && - validRequiredIfOperators.includes( - enviromentVariables[eachEnvironmentVariable].requiredIf.operator - ) && - enviromentVariables[eachEnvironmentVariable].requiredIf.value && - enviromentVariables[eachEnvironmentVariable].requiredIf.value != "" - ) { - switch ( - enviromentVariables[eachEnvironmentVariable].requiredIf.operator - ) { - case "EQUALS": - if ( - process.env[ - enviromentVariables[eachEnvironmentVariable].requiredIf.key - ] === enviromentVariables[eachEnvironmentVariable].requiredIf.value - ) { - enviromentVariables[eachEnvironmentVariable].optional = false; - } - break; - case "NOT_EQUALS": - if ( - process.env[ - enviromentVariables[eachEnvironmentVariable].requiredIf.key - ] != enviromentVariables[eachEnvironmentVariable].requiredIf.value - ) { - enviromentVariables[eachEnvironmentVariable].optional = false; - } - break; - default: - break; - } - } - - if (enviromentVariables[eachEnvironmentVariable].optional === false) { - if ( - !process.env[eachEnvironmentVariable] || - process.env[eachEnvironmentVariable] == "" - ) { - success = false; - keyCheckPass = false; - } else if ( - enviromentVariables[eachEnvironmentVariable].possibleValues && - Array.isArray( - enviromentVariables[eachEnvironmentVariable].possibleValues - ) && - enviromentVariables[eachEnvironmentVariable].possibleValues.length > 0 - ) { - if ( - !enviromentVariables[eachEnvironmentVariable].possibleValues.includes( - process.env[eachEnvironmentVariable] - ) - ) { - success = false; - keyCheckPass = false; - enviromentVariables[ - eachEnvironmentVariable - ].message += ` Valid values - ${enviromentVariables[ - eachEnvironmentVariable - ].possibleValues.join(", ")}`; - } - } - } - - if ( - (!process.env[eachEnvironmentVariable] || - process.env[eachEnvironmentVariable] == "") && - enviromentVariables[eachEnvironmentVariable].default && - enviromentVariables[eachEnvironmentVariable].default != "" - ) { - process.env[eachEnvironmentVariable] = - enviromentVariables[eachEnvironmentVariable].default; - success = true; - keyCheckPass = true; - } - - if (!keyCheckPass) { - if (enviromentVariables[eachEnvironmentVariable].message !== "") { - tableObj[eachEnvironmentVariable] = - enviromentVariables[eachEnvironmentVariable].message; - } else { - tableObj[ - eachEnvironmentVariable - ] = `FAILED - ${eachEnvironmentVariable} is required`; - } - } - tableData.push(tableObj); - }); - - log.info(tableData.toString()); - getKid(); - return { - success: success, - }; -}; - -async function getKid() { - if (process.env.PROJECT_CERTIFICATE_ON_OFF === "ON") { - // get certificate issuer kid from sunbird-RC - let kidData = await certificateService.getCertificateIssuerKid(); - if (!kidData.success) { - console.log("failed to get kid value from registry service : ", kidData); - if ( - process.env.CERTIFICATE_ISSUER_KID && - process.env.CERTIFICATE_ISSUER_KID != "" - ) { - global.CERTIFICATE_ISSUER_KID = process.env.CERTIFICATE_ISSUER_KID; - } - // console.log("Server stoped . Failed to set certificate issuer Kid value") - // process.exit(); - } else { - console.log("Kid data fetched successfully : ", kidData.data); - global.CERTIFICATE_ISSUER_KID = kidData.data; - } - console.log(JSON.stringify(kidData)); - // global.CERTIFICATE_ISSUER_KID = kidData.data - } -} + const Log = require("log"); + let log = new Log("debug"); + let table = require("cli-table"); + const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); + + let tableData = new table(); + + let enviromentVariables = { + "APPLICATION_PORT" : { + "message" : "Please specify the value for e.g. 4201", + "optional" : false + }, + "APPLICATION_ENV" : { + "message" : "Please specify the value for e.g. local/development/qa/production", + "optional" : false + }, + "MONGODB_URL" : { + "message" : "Required mongodb url", + "optional" : false + }, + "INTERNAL_ACCESS_TOKEN" : { + "message" : "Required internal access token", + "optional" : false + }, + "KAFKA_COMMUNICATIONS_ON_OFF" : { + "message" : "Enable/Disable kafka communications", + "optional" : false + }, + "KAFKA_URL" : { + "message" : "Required", + "optional" : false + }, + "USER_SERVICE_URL" : { + "message" : "Required user service base url", + "optional" : false + }, + "SERVICE_NAME" : { + "message" : "current service name", + "optional" : true, + "default" : "ml-projects-service" + }, + "CERTIFICATE_SERVICE_URL" : { + "message" : "certificate service base url", + "optional" : true, + "default" : "http://registry-service:8081", + "requiredIf" : { + "key": "PROJECT_CERTIFICATE_ON_OFF", + "operator" : "EQUALS", + "value" : "ON" + } + }, + "PROJECT_CERTIFICATE_ON_OFF" : { + "message" : "Enable/Disable project certification", + "optional" : false, + "default" : "ON" + }, + "USER_DELETE_TOPIC": { + message: "Required user delete kafka consumer topic name", + optional: false, + }, + "ID": { + message: "Required Service ID", + optional: false, + }, + "TELEMETRY_ON_OFF":{ + message: "Required telemetry on/off status", + optional: false, + }, + "TELEMETRY_TOPIC": { + message: "Required telemetry topic", + optional: false, + }, + } + + let success = true; + + module.exports = function() { + Object.keys(enviromentVariables).forEach(eachEnvironmentVariable=>{ + + let tableObj = { + [eachEnvironmentVariable] : "PASSED" + }; + + let keyCheckPass = true; + let validRequiredIfOperators = ["EQUALS","NOT_EQUALS"] + + if(enviromentVariables[eachEnvironmentVariable].optional === true + && enviromentVariables[eachEnvironmentVariable].requiredIf + && enviromentVariables[eachEnvironmentVariable].requiredIf.key + && enviromentVariables[eachEnvironmentVariable].requiredIf.key != "" + && enviromentVariables[eachEnvironmentVariable].requiredIf.operator + && validRequiredIfOperators.includes(enviromentVariables[eachEnvironmentVariable].requiredIf.operator) + && enviromentVariables[eachEnvironmentVariable].requiredIf.value + && enviromentVariables[eachEnvironmentVariable].requiredIf.value != "") { + switch (enviromentVariables[eachEnvironmentVariable].requiredIf.operator) { + case "EQUALS": + if(process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] === enviromentVariables[eachEnvironmentVariable].requiredIf.value) { + enviromentVariables[eachEnvironmentVariable].optional = false; + } + break; + case "NOT_EQUALS": + if(process.env[enviromentVariables[eachEnvironmentVariable].requiredIf.key] != enviromentVariables[eachEnvironmentVariable].requiredIf.value) { + enviromentVariables[eachEnvironmentVariable].optional = false; + } + break; + default: + break; + } + } + + if(enviromentVariables[eachEnvironmentVariable].optional === false) { + if(!(process.env[eachEnvironmentVariable]) + || process.env[eachEnvironmentVariable] == "") { + success = false; + keyCheckPass = false; + } else if (enviromentVariables[eachEnvironmentVariable].possibleValues + && Array.isArray(enviromentVariables[eachEnvironmentVariable].possibleValues) + && enviromentVariables[eachEnvironmentVariable].possibleValues.length > 0) { + if(!enviromentVariables[eachEnvironmentVariable].possibleValues.includes(process.env[eachEnvironmentVariable])) { + success = false; + keyCheckPass = false; + enviromentVariables[eachEnvironmentVariable].message += ` Valid values - ${enviromentVariables[eachEnvironmentVariable].possibleValues.join(", ")}` + } + } + } + + if((!(process.env[eachEnvironmentVariable]) + || process.env[eachEnvironmentVariable] == "") + && enviromentVariables[eachEnvironmentVariable].default + && enviromentVariables[eachEnvironmentVariable].default != "") { + process.env[eachEnvironmentVariable] = enviromentVariables[eachEnvironmentVariable].default; + success = true; + keyCheckPass = true; + } + + if(!keyCheckPass) { + if(enviromentVariables[eachEnvironmentVariable].message !== "") { + tableObj[eachEnvironmentVariable] = + enviromentVariables[eachEnvironmentVariable].message; + } else { + tableObj[eachEnvironmentVariable] = `FAILED - ${eachEnvironmentVariable} is required`; + } + } + tableData.push(tableObj); + }) + + log.info(tableData.toString()); + getKid(); + return { + success : success + } + } + + async function getKid(){ + if ( process.env.PROJECT_CERTIFICATE_ON_OFF === "ON" ) { + // get certificate issuer kid from sunbird-RC + let kidData = await certificateService.getCertificateIssuerKid(); + if( !kidData.success ) { + console.log("failed to get kid value from registry service : ",kidData) + if( process.env.CERTIFICATE_ISSUER_KID && process.env.CERTIFICATE_ISSUER_KID != "" ) { + global.CERTIFICATE_ISSUER_KID = process.env.CERTIFICATE_ISSUER_KID; + } + // console.log("Server stoped . Failed to set certificate issuer Kid value") + // process.exit(); + } else { + console.log("Kid data fetched successfully : ",kidData.data) + global.CERTIFICATE_ISSUER_KID = kidData.data + } + console.log(JSON.stringify(kidData)) + // global.CERTIFICATE_ISSUER_KID = kidData.data + } + }; + + + + \ No newline at end of file diff --git a/generics/constants/common.js b/generics/constants/common.js index c6abbc71..93dfb8c9 100644 --- a/generics/constants/common.js +++ b/generics/constants/common.js @@ -5,59 +5,62 @@ * Description : All common messages. */ -module.exports = { - ACTIVE_STATUS: "active", - PUBLISHED: "published", - SUCCESS: "Success", - ASSESSMENT: "assessment", - CONTENT: "content", - IMPROVEMENT_PROJECT: "improvementProject", - MULTIPLE: "multiple", - OTHERS: "Others", - SIMPLE_TASK_TYPE: "simple", - NOT_STARTED: "not started", - RECENTLY_ADDED_PROJECT: "currentlyAdded", - IMPORTANT_PROJECT: "importantProject", - COMPLETED_STATUS: "completed", - INPROGRESS_STATUS: "inProgress", - NOT_STARTED_STATUS: "notStarted", - STARTED: "started", - SUBMITTED_STATUS: "submitted", - OBSERVATION: "observation", - PUBLISHED_STATUS: "published", - LEAD_ASSESSOR: "LEAD_ASSESSOR", - PROJECT_DESCRIPTION: - "Manage and track your school improvement easily, by creating tasks and planning project timelines.", - RESOURCE_TYPE: "Improvement Project Solution", - ENGLISH_LANGUAGE: "English", - KEYWORDS: "Improvement Project", - ASSIGN_TO_ME: "assignedToMe", - CREATED_BY_ME: "createdByMe", - DEFAULT_PAGE_NO: 1, - DEFAULT_PAGE_SIZE: 100, - OBSERVATION_REFERENCE_KEY: "observation", - ALLOW_MULTIPLE_ASSESSMENTS: "allowMultipleAssessemts", - IS_RUBRIC_DRIVEN: "isRubricDriven", - CRITERIA_LEVEL_REPORT: "criteriaLevelReport", - LINK: "link", - DEFAULT_SUBMISSION_REQUIRED: 1, - TASK_SEQUENCE: "taskSequence", - CHILDREN: "children", - ATTACHMENT_TYPE_LINK: "link", - PROJECT_ATTACHMENT: "project", - TASK_ATTACHMENT: "task", - DEFAULT_TASK_COMPLETED: 0, - IMAGE_DATA_TYPE: "image/jpeg", - DISTRICT: "district", - SERVER_TIME_OUT: 5000, - OK: "OK", - PROJECT: "project", - PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY: - "Certificate generated successfully", - DELETED_USER: "Deleted User", - TELEMTRY_EVENT_LOGGER: "TelemetryEventLogger", - INFO_LEVEL: "INFO", - DELETE_STATE: "Delete", - USER_DELETE_TYPE: "DeleteUserStatus", - AUDIT: "AUDIT", + module.exports = { + "ACTIVE_STATUS" : "active", + "PUBLISHED" : "published", + "SUCCESS" : "Success", + "ASSESSMENT" : "assessment", + "CONTENT" : "content", + "IMPROVEMENT_PROJECT" : "improvementProject", + "MULTIPLE" : "multiple", + "OTHERS" : "Others", + "SIMPLE_TASK_TYPE" : "simple", + "NOT_STARTED" : "not started", + "RECENTLY_ADDED_PROJECT" : "currentlyAdded", + "IMPORTANT_PROJECT" : "importantProject", + "COMPLETED_STATUS" : "completed", + "INPROGRESS_STATUS" : "inProgress", + "NOT_STARTED_STATUS" : "notStarted", + "STARTED":"started", + "SUBMITTED_STATUS":"submitted", + "OBSERVATION" : "observation", + "PUBLISHED_STATUS" : "published", + "LEAD_ASSESSOR" : "LEAD_ASSESSOR", + "PROJECT_DESCRIPTION" : "Manage and track your school improvement easily, by creating tasks and planning project timelines.", + "RESOURCE_TYPE" : "Improvement Project Solution", + "ENGLISH_LANGUAGE" : "English", + "KEYWORDS" : "Improvement Project", + "ASSIGN_TO_ME" : "assignedToMe", + "CREATED_BY_ME" : "createdByMe", + "DEFAULT_PAGE_NO" : 1, + "DEFAULT_PAGE_SIZE" : 100, + "OBSERVATION_REFERENCE_KEY" : "observation", + "ALLOW_MULTIPLE_ASSESSMENTS" : "allowMultipleAssessemts", + "IS_RUBRIC_DRIVEN" : "isRubricDriven", + "CRITERIA_LEVEL_REPORT" : "criteriaLevelReport", + "LINK" : "link", + "DEFAULT_SUBMISSION_REQUIRED" : 1, + "TASK_SEQUENCE" : "taskSequence", + "CHILDREN" : "children", + "ATTACHMENT_TYPE_LINK" : "link", + "PROJECT_ATTACHMENT" : "project", + "TASK_ATTACHMENT" : "task", + "DEFAULT_TASK_COMPLETED" : 0, + "IMAGE_DATA_TYPE" : "image/jpeg", + "DISTRICT": "district", + "SERVER_TIME_OUT" : 5000, + "OK" : "OK", + "PROJECT" : "project", + "PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY" : "Certificate generated successfully", + "TELEMETRY_VERSION": "3.0", + "DELETED_USER": "Deleted User", + "TELEMTRY_EVENT_LOGGER": "TelemetryEventLogger", + "INFO_LEVEL": "INFO", + "DELETE_STATE": "Delete", + "USER_DELETE_TYPE": "DeleteUserStatus", + "AUDIT": "AUDIT", + "DELETE_USER": "delete-user", + "USER": "User", + "USER_DELETE_MODULE": "userDelete", + "OFF" : "OFF", }; diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index e8dabee0..ea285087 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -3,18 +3,17 @@ * author : Aman Karki * Date : 13-July-2020 * Description : All utility functions. - */ +*/ // Dependencies -const { validate: uuidValidate, v4: uuidV4 } = require("uuid"); +const {validate : uuidValidate,v4 : uuidV4} = require('uuid'); const packageData = require(PROJECT_ROOT_DIRECTORY + "/package.json"); - /** - * convert camel case to title case. - * @function - * @name camelCaseToTitleCase - * @param {String} in_camelCaseString - String of camel case. - * @returns {String} returns a titleCase string. ex: helloThereMister, o/p: Hello There Mister - */ + * convert camel case to title case. + * @function + * @name camelCaseToTitleCase + * @param {String} in_camelCaseString - String of camel case. + * @returns {String} returns a titleCase string. ex: helloThereMister, o/p: Hello There Mister +*/ function camelCaseToTitleCase(in_camelCaseString) { var result = in_camelCaseString // "ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D" @@ -37,141 +36,135 @@ function camelCaseToTitleCase(in_camelCaseString) { return result.charAt(0).toUpperCase() + result.slice(1); } -/** - * Convert hyphen case string to camelCase. - * @function - * @name hyphenCaseToCamelCase - * @param {String} string - String in hyphen case. - * @returns {String} returns a camelCase string. - */ + /** + * Convert hyphen case string to camelCase. + * @function + * @name hyphenCaseToCamelCase + * @param {String} string - String in hyphen case. + * @returns {String} returns a camelCase string. +*/ function hyphenCaseToCamelCase(string) { - return string.replace(/-([a-z])/g, function (g) { - return g[1].toUpperCase(); - }); + return string.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); } -/** - * convert string to lowerCase. - * @function - * @name lowerCase - * @param {String} str - * @returns {String} returns a lowercase string. ex: HELLO, o/p: hello - */ + /** + * convert string to lowerCase. + * @function + * @name lowerCase + * @param {String} str + * @returns {String} returns a lowercase string. ex: HELLO, o/p: hello +*/ function lowerCase(str) { - return str.toLowerCase(); + return str.toLowerCase() } -/** - * check whether the given string is url. - * @function - * @name checkIfStringIsUrl - check whether string is url or not. - * @param {String} str - * @returns {Boolean} returns a Boolean value. ex:"http://example.com:3000/pathname/?search=test" , o/p:true - */ + /** + * check whether the given string is url. + * @function + * @name checkIfStringIsUrl - check whether string is url or not. + * @param {String} str + * @returns {Boolean} returns a Boolean value. ex:"http://example.com:3000/pathname/?search=test" , o/p:true +*/ function checkIfStringIsUrl(str) { - var pattern = new RegExp( - "^(https?:\\/\\/)?" + // protocol - "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|" + // domain name - "((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address - "(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path - "(\\?[;&a-z\\d%_.~+=-]*)?" + // query string - "(\\#[-a-z\\d_]*)?$", - "i" - ); // fragment locator + var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string + '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator return pattern.test(str); } -/** - * Parse a single column. - * @function - * @name valueParser - Parse value - * @param {String} dataToBeParsed - data to be parsed. - * @returns {Object} returns parsed data - */ + /** + * Parse a single column. + * @function + * @name valueParser - Parse value + * @param {String} dataToBeParsed - data to be parsed. + * @returns {Object} returns parsed data +*/ function valueParser(dataToBeParsed) { - let parsedData = {}; - Object.keys(dataToBeParsed).forEach((eachDataToBeParsed) => { - parsedData[eachDataToBeParsed] = dataToBeParsed[eachDataToBeParsed].trim(); - }); + let parsedData = {} + + Object.keys(dataToBeParsed).forEach(eachDataToBeParsed => { + parsedData[eachDataToBeParsed] = dataToBeParsed[eachDataToBeParsed].trim() + }) - if ( - parsedData._arrayFields && - parsedData._arrayFields.split(",").length > 0 - ) { - parsedData._arrayFields.split(",").forEach((arrayTypeField) => { + if(parsedData._arrayFields && parsedData._arrayFields.split(",").length > 0) { + parsedData._arrayFields.split(",").forEach(arrayTypeField => { if (parsedData[arrayTypeField]) { - parsedData[arrayTypeField] = parsedData[arrayTypeField].split(","); + parsedData[arrayTypeField] = parsedData[arrayTypeField].split(",") } - }); + }) } - return parsedData; + return parsedData } /** - * Convert string to boolean. - * @method - * @name convertStringToBoolean - * @param {String} stringData -String data. - * @returns {Boolean} - Boolean data. - */ + * Convert string to boolean. + * @method + * @name convertStringToBoolean + * @param {String} stringData -String data. + * @returns {Boolean} - Boolean data. + */ + + function convertStringToBoolean(stringData) { + let stringToBoolean = (stringData === "TRUE" || stringData === "true" || stringData === true ); + return stringToBoolean; + } -function convertStringToBoolean(stringData) { - let stringToBoolean = - stringData === "TRUE" || stringData === "true" || stringData === true; - return stringToBoolean; -} + /** + * List of boolean data from a given model. + * @method + * @name getAllBooleanDataFromModels + * @param schema - schema + * @returns {Array} Boolean data. + */ -/** - * List of boolean data from a given model. - * @method - * @name getAllBooleanDataFromModels - * @param schema - schema - * @returns {Array} Boolean data. - */ + function getAllBooleanDataFromModels(schema) { -function getAllBooleanDataFromModels(schema) { - let defaultSchema = Object.keys(schema); + let defaultSchema = Object.keys(schema); - let booleanValues = []; + let booleanValues = []; - defaultSchema.forEach((singleSchemaKey) => { - let currentSchema = schema[singleSchemaKey]; + defaultSchema.forEach(singleSchemaKey=>{ - if ( - currentSchema.hasOwnProperty("default") && - typeof currentSchema.default === "boolean" - ) { - booleanValues.push(singleSchemaKey); - } - }); + let currentSchema = schema[singleSchemaKey]; - return booleanValues; -} + if( + currentSchema.hasOwnProperty('default') && + typeof currentSchema.default === "boolean" + ) { + booleanValues.push(singleSchemaKey); + } + }); -/** - * check whether id is mongodbId or not. - * @function - * @name isValidMongoId - * @param {String} id - * @returns {Boolean} returns whether id is valid mongodb id or not. - */ + return booleanValues; + } -function isValidMongoId(id) { - return ObjectId.isValid(id) && new ObjectId(id).toString() === id; -} + /** + * check whether id is mongodbId or not. + * @function + * @name isValidMongoId + * @param {String} id + * @returns {Boolean} returns whether id is valid mongodb id or not. + */ -/** - * Get epoch time from current date. - * @function - * @name epochTime - * @returns {Date} returns epoch time. - */ + function isValidMongoId(id) { + return ObjectId.isValid(id) && new ObjectId(id).toString() === id; + } + + /** + * Get epoch time from current date. + * @function + * @name epochTime + * @returns {Date} returns epoch time. + */ function epochTime() { var currentDate = new Date(); @@ -180,152 +173,158 @@ function epochTime() { } /** - * Convert Project Status - * @function - * @name convertProjectStatus - * @returns {String} returns converted project status - */ + * Convert Project Status + * @function + * @name convertProjectStatus + * @returns {String} returns converted project status + */ function convertProjectStatus(status) { - let convertedStatus; - if (status == CONSTANTS.common.NOT_STARTED_STATUS) { - convertedStatus = CONSTANTS.common.STARTED; - } else if (status == CONSTANTS.common.COMPLETED_STATUS) { - convertedStatus = CONSTANTS.common.SUBMITTED_STATUS; - } else { - convertedStatus = status; - } - - return convertedStatus; + let convertedStatus; + + if ( status == CONSTANTS.common.NOT_STARTED_STATUS ) { + convertedStatus = CONSTANTS.common.STARTED; + } else if ( status == CONSTANTS.common.COMPLETED_STATUS ) { + convertedStatus = CONSTANTS.common.SUBMITTED_STATUS; + } else { + convertedStatus = status; + } + + return convertedStatus; } /** - * Revert Project Status For Older App - * @function - * @name revertProjectStatus - * @returns {String} returns reverted project status - */ + * Revert Project Status For Older App + * @function + * @name revertProjectStatus + * @returns {String} returns reverted project status + */ + + function revertProjectStatus(status) { -function revertProjectStatus(status) { let revertedStatus; - if (status == CONSTANTS.common.STARTED) { - revertedStatus = CONSTANTS.common.NOT_STARTED_STATUS; - } else if (status == CONSTANTS.common.SUBMITTED_STATUS) { - revertedStatus = CONSTANTS.common.COMPLETED_STATUS; + if ( status == CONSTANTS.common.STARTED ) { + revertedStatus = CONSTANTS.common.NOT_STARTED_STATUS; + } else if ( status == CONSTANTS.common.SUBMITTED_STATUS ) { + revertedStatus = CONSTANTS.common.COMPLETED_STATUS; } else { - revertedStatus = status; - } + revertedStatus = status; + } return revertedStatus; } /** - * revert status or not - * @method - * @name revertStatusorNot - * @param {String} appVersion - app Version. - * @returns {Boolean} - true or false - */ + * revert status or not + * @method + * @name revertStatusorNot + * @param {String} appVersion - app Version. + * @returns {Boolean} - true or false +*/ + +function revertStatusorNot( appVersion ) { -function revertStatusorNot(appVersion) { - let versions = ["4.10", "4.11", "4.12"]; + let versions = ["4.10", "4.11", "4.12" ]; - let appVer = appVersion.split(".", 2).join("."); - if (versions.includes(appVer)) { - return false; + let appVer = appVersion.split('.',2).join('.'); + if ( versions.includes(appVer)) { + return false } else { - let appVersionNo = Number(appVer); - if (!isNaN(appVersionNo) && appVersionNo < 4.7) { - return true; - } else { - return false; - } + + let appVersionNo = Number(appVer); + if ( !isNaN(appVersionNo) && appVersionNo < 4.7 ) { + return true + } else { + return false + } } + } /** - * check whether string is valid uuid. - * @function - * @name checkValidUUID - * @param {String} uuids - * @returns {Boolean} returns a Boolean value true/false - */ + * check whether string is valid uuid. + * @function + * @name checkValidUUID + * @param {String} uuids + * @returns {Boolean} returns a Boolean value true/false +*/ function checkValidUUID(uuids) { + var validateUUID = true; - if (Array.isArray(uuids)) { - for (var i = 0; uuids.length > i; i++) { - if (!uuidValidate(uuids[i])) { - validateUUID = false; + if(Array.isArray(uuids)){ + for (var i = 0; uuids.length > i; i++) { + if(!uuidValidate(uuids[i])){ + validateUUID = false + } } - } - } else { - validateUUID = uuidValidate(uuids); + }else { + validateUUID = uuidValidate(uuids); } return validateUUID; } /** - * make dates comparable - * @function - * @name createComparableDates - * @param {String} dateArg1 - * @param {String} dateArg2 - * @returns {Object} - date object - */ + * make dates comparable + * @function + * @name createComparableDates + * @param {String} dateArg1 + * @param {String} dateArg2 + * @returns {Object} - date object +*/ function createComparableDates(dateArg1, dateArg2) { - let date1; - if (typeof dateArg1 === "string") { - date1 = new Date(dateArg1.replace(/(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")); + let date1 + if(typeof dateArg1 === "string") { + date1 = new Date(dateArg1.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")) } else { - date1 = new Date(dateArg1); + date1 = new Date(dateArg1) } - - let date2; - if (typeof dateArg2 === "string") { - date2 = new Date(dateArg2.replace(/(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")); + + let date2 + if(typeof dateArg2 === "string") { + date2 = new Date(dateArg2.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3")) } else { - date2 = new Date(dateArg2); + date2 = new Date(dateArg2) } - date1.setHours(0); - date1.setMinutes(0); - date1.setSeconds(0); - date2.setHours(0); - date2.setMinutes(0); - date2.setSeconds(0); - return { + date1.setHours(0) + date1.setMinutes(0) + date1.setSeconds(0) + date2.setHours(0) + date2.setMinutes(0) + date2.setSeconds(0) + return({ dateOne: date1, - dateTwo: date2, - }; + dateTwo: date2 + }) } /** - * count attachments - * @function - * @name noOfElementsInArray - * @param {Object} data - data to count - * @param {Object} filter - filter data - * @returns {Number} - attachment count - */ + * count attachments + * @function + * @name noOfElementsInArray + * @param {Object} data - data to count + * @param {Object} filter - filter data + * @returns {Number} - attachment count +*/ function noOfElementsInArray(data, filter = {}) { - if (!filter || !Object.keys(filter).length > 0) { + if ( !filter || !Object.keys(filter).length > 0 ) { return data.length; } - if (!data.length > 0) { + if ( !data.length > 0 ) { return 0; } else { - if (filter.value == "all") { + if ( filter.value == "all" ){ return data.length; } else { let count = 0; - for (let attachment = 0; attachment < data.length; attachment++) { - if (data[attachment][filter.key] == filter.value) { - count++; + for ( let attachment = 0; attachment < data.length; attachment++ ) { + if ( data[attachment][filter.key] == filter.value ) { + count++ } } return count; @@ -334,90 +333,111 @@ function noOfElementsInArray(data, filter = {}) { } /** - * validate lhs and rhs using operator passed as String/ Number + * validate lhs and rhs using operator passed as String/ Number + * @function + * @name operatorValidation + * @param {Number or String} valueLhs + * @param {Number or String} valueRhs + * @returns {Boolean} - validation result +*/ + +function operatorValidation(valueLhs, valueRhs, operator) { + return new Promise(async (resolve, reject) => { + let result = false; + if (operator == "==" ) { + result = (valueLhs == valueRhs) ? true : false + } else if (operator == "!=" ) { + result = (valueLhs != valueRhs) ? true : false + } else if (operator == ">" ) { + result = (valueLhs > valueRhs) ? true : false + } else if (operator == "<" ) { + result = (valueLhs < valueRhs) ? true : false + } else if (operator == "<=" ) { + result = (valueLhs <= valueRhs) ? true : false + } else if (operator == ">=" ) { + result = (valueLhs >= valueRhs) ? true : false + } + return resolve(result) + }) +} + +/** + * generate uuid * @function - * @name operatorValidation - * @param {Number or String} valueLhs - * @param {Number or String} valueRhs - * @returns {Boolean} - validation result + * @name generateUUId + * @returns {String} returns uuid. */ -function operatorValidation(valueLhs, valueRhs, operator) { - return new Promise(async (resolve, reject) => { - let result = false; - if (operator == "==") { - result = valueLhs == valueRhs ? true : false; - } else if (operator == "!=") { - result = valueLhs != valueRhs ? true : false; - } else if (operator == ">") { - result = valueLhs > valueRhs ? true : false; - } else if (operator == "<") { - result = valueLhs < valueRhs ? true : false; - } else if (operator == "<=") { - result = valueLhs <= valueRhs ? true : false; - } else if (operator == ">=") { - result = valueLhs >= valueRhs ? true : false; - } - return resolve(result); - }); +function generateUUId() { + return uuidV4(); } + /** - * generate telemetry raw event + * generate skeleton telemetry raw event * @function - * @name getTelemetryEvent + * @name generateTelemetryEventSkeletonStructure * @returns {Object} returns uuid. */ -function getTelemetryEvent() { - let telemetryEvent = { + function generateTelemetryEventSkeletonStructure() { + let telemetrySkeleton = { eid: "", ets: epochTime(), - ver: "3.0", + ver: CONSTANTS.common.TELEMETRY_VERSION, mid: generateUUId(), actor: {}, context: { channel: "", pdata: { id: process.env.ID, - pid: "manage-learn", ver: packageData.version, }, env: "", - cdata: [{ id: generateUUId(), type: "Request" }], + cdata: [], rollup: {}, }, object: {}, edata: {}, }; - return telemetryEvent; + return telemetrySkeleton; } + /** - * generate uuid + * generate telemetry event * @function - * @name generateUUId - * @returns {String} returns uuid. + * @name generateTelemetryEvent + * @returns {Object} returns uuid. */ - -function generateUUId() { - return uuidV4(); + function generateTelemetryEvent(rawEvent) { + let telemetryEvent = { + timestamp: new Date(), + msg: JSON.stringify(rawEvent), + lname: "", + tname: "", + level: "", + HOSTNAME: "", + "application.home": "", + }; + return telemetryEvent; } module.exports = { - camelCaseToTitleCase: camelCaseToTitleCase, - lowerCase: lowerCase, - checkIfStringIsUrl: checkIfStringIsUrl, - hyphenCaseToCamelCase: hyphenCaseToCamelCase, - valueParser: valueParser, - convertStringToBoolean: convertStringToBoolean, - getAllBooleanDataFromModels: getAllBooleanDataFromModels, - epochTime: epochTime, - isValidMongoId: isValidMongoId, - convertProjectStatus: convertProjectStatus, - revertProjectStatus: revertProjectStatus, - revertStatusorNot: revertStatusorNot, - checkValidUUID: checkValidUUID, - createComparableDates: createComparableDates, - noOfElementsInArray: noOfElementsInArray, - operatorValidation: operatorValidation, - getTelemetryEvent: getTelemetryEvent, + camelCaseToTitleCase : camelCaseToTitleCase, + lowerCase : lowerCase, + checkIfStringIsUrl : checkIfStringIsUrl, + hyphenCaseToCamelCase : hyphenCaseToCamelCase, + valueParser : valueParser, + convertStringToBoolean : convertStringToBoolean, + getAllBooleanDataFromModels : getAllBooleanDataFromModels, + epochTime : epochTime, + isValidMongoId : isValidMongoId, + convertProjectStatus : convertProjectStatus, + revertProjectStatus:revertProjectStatus, + revertStatusorNot:revertStatusorNot, + checkValidUUID : checkValidUUID, + createComparableDates : createComparableDates, + noOfElementsInArray : noOfElementsInArray, + operatorValidation : operatorValidation, + generateTelemetryEventSkeletonStructure : generateTelemetryEventSkeletonStructure, + generateTelemetryEvent : generateTelemetryEvent }; diff --git a/generics/kafka/consumers/userDMS.js b/generics/kafka/consumers/userDelete.js similarity index 92% rename from generics/kafka/consumers/userDMS.js rename to generics/kafka/consumers/userDelete.js index 7cb78372..f1aa5a3e 100644 --- a/generics/kafka/consumers/userDMS.js +++ b/generics/kafka/consumers/userDelete.js @@ -27,8 +27,8 @@ var messageReceived = function (message) { return new Promise(async function (resolve, reject) { try { let parsedMessage = JSON.parse(message.value); - if (parsedMessage.edata.action === "delete-user") { - let userDataDeleteStatus = await userProjectsHelper.userDelete( + if (parsedMessage.edata.action === CONSTANTS.common.DELETE_USER) { + let userDataDeleteStatus = await userProjectsHelper.deleteUserPIIData( parsedMessage ); if (userDataDeleteStatus.success === true) { diff --git a/generics/kafka/producers.js b/generics/kafka/producers.js index 02f6345e..605679b5 100644 --- a/generics/kafka/producers.js +++ b/generics/kafka/producers.js @@ -3,47 +3,38 @@ * author : Aman Karki * created-date : 08-Sep-2020 * Description : Kafka Producer related information. - */ +*/ // Dependencies -const kafkaCommunicationsOnOff = - !process.env.KAFKA_COMMUNICATIONS_ON_OFF || - process.env.KAFKA_COMMUNICATIONS_ON_OFF != "OFF" - ? "ON" - : "OFF"; -const projectSubmissionTopic = - process.env.PROJECT_SUBMISSION_TOPIC && - process.env.PROJECT_SUBMISSION_TOPIC != "OFF" - ? process.env.PROJECT_SUBMISSION_TOPIC - : "sl-improvement-project-submission-dev"; -const telemetryEventTopic = process.env.TELEMETRY_TOPIC - ? process.env.TELEMETRY_TOPIC - : "sl-telemetry-dev"; -const userDeleteTopic = process.env.USER_DELETE_TOPIC; +const kafkaCommunicationsOnOff = (!process.env.KAFKA_COMMUNICATIONS_ON_OFF || process.env.KAFKA_COMMUNICATIONS_ON_OFF != "OFF") ? "ON" : "OFF"; +const projectSubmissionTopic = (process.env.PROJECT_SUBMISSION_TOPIC && process.env.PROJECT_SUBMISSION_TOPIC != "OFF") ? process.env.PROJECT_SUBMISSION_TOPIC : "sl-improvement-project-submission-dev"; +const telemetryEventTopic = process.env.TELEMETRY_TOPIC ? process.env.TELEMETRY_TOPIC : "dev.telemetry.raw"; /** - * Push improvement projects to kafka. - * @function - * @name pushProjectToKafka - * @param {Object} message - Message data. - */ + * Push improvement projects to kafka. + * @function + * @name pushProjectToKafka + * @param {Object} message - Message data. +*/ const pushProjectToKafka = function (message) { return new Promise(async (resolve, reject) => { - try { - let kafkaPushStatus = await pushMessageToKafka([ - { - topic: projectSubmissionTopic, - messages: JSON.stringify(message), - }, - ]); + try { + + let kafkaPushStatus = await pushMessageToKafka([{ + topic: projectSubmissionTopic, + messages: JSON.stringify(message) + }]); + + return resolve(kafkaPushStatus); + + } catch (error) { + return reject(error); + } + }) +} + - return resolve(kafkaPushStatus); - } catch (error) { - return reject(error); - } - }); -}; /** * Push message to telemetry. @@ -51,7 +42,7 @@ const pushProjectToKafka = function (message) { * @name pushTelemetryEventToKafka * @param {Object} message - Message data. */ -const pushTelemetryEventToKafka = function (message) { + const pushTelemetryEventToKafka = function (message) { return new Promise(async (resolve, reject) => { try { let kafkaPushStatus = await pushMessageToKafka([ @@ -60,7 +51,7 @@ const pushTelemetryEventToKafka = function (message) { messages: JSON.stringify(message), }, ]); - + return resolve(kafkaPushStatus); } catch (error) { return reject(error); @@ -69,56 +60,51 @@ const pushTelemetryEventToKafka = function (message) { }; /** - * Push message to kafka. - * @function - * @name pushMessageToKafka - * @param {Object} payload - Payload data. - */ + * Push message to kafka. + * @function + * @name pushMessageToKafka + * @param {Object} payload - Payload data. +*/ -const pushMessageToKafka = function (payload) { +const pushMessageToKafka = function(payload) { return new Promise((resolve, reject) => { + if (kafkaCommunicationsOnOff != "ON") { throw reject("Kafka configuration is not done"); } console.log("-------Kafka producer log starts here------------------"); - console.log("Topic Name: ", payload[0].topic); + console.log("Topic Name: ", payload[0].topic); console.log("Message: ", JSON.stringify(payload)); console.log("-------Kafka producer log ends here------------------"); + kafkaClient.kafkaProducer.send(payload, (err, data) => { if (err) { - return reject("Kafka push to topic " + payload[0].topic + " failed."); + return reject("Kafka push to topic "+ payload[0].topic +" failed."); } else { return resolve(data); } - }); - }) - .then((result) => { - console.log( - "Kafka push to topic " + - payload[0].topic + - " successful with number - " + - result[payload[0].topic][0] - ); - return { - status: CONSTANTS.common.SUCCESS, - message: - "Kafka push to topic " + - payload[0].topic + - " successful with number - " + - result[payload[0].topic][0], - }; }) - .catch((err) => { - return { - status: "failed", - message: err, - }; - }); -}; + + }).then(result => { + + return { + status : CONSTANTS.common.SUCCESS, + message: "Kafka push to topic "+ payload[0].topic +" successful with number - "+result[payload[0].topic][0] + }; + + }).catch((err) => { + return { + status : "failed", + message: err + } + }) +} + module.exports = { - pushProjectToKafka: pushProjectToKafka, - pushTelemetryEventToKafka: pushTelemetryEventToKafka, + pushProjectToKafka : pushProjectToKafka, + pushTelemetryEventToKafka : pushTelemetryEventToKafka }; + diff --git a/generics/services/users.js b/generics/services/users.js index 48b05fc2..a7961f89 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -6,246 +6,236 @@ */ //dependencies -const request = require("request"); +const request = require('request'); const userServiceUrl = process.env.USER_SERVICE_URL; -const profile = function (token, userId = "") { - return new Promise(async (resolve, reject) => { - try { - let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_V5; - - if (userId !== "") { - url = - url + - "/" + - userId + - "?" + - "fields=organisations,roles,locations,declarations,externalIds"; - } +const profile = function ( token,userId = "" ) { + return new Promise(async (resolve, reject) => { + try { + + let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_V5; + + if( userId !== "" ) { + url = url + "/" + userId + "?" + "fields=organisations,roles,locations,declarations,externalIds" + } - const options = { - headers: { - "content-type": "application/json", - "x-authenticated-user-token": token, - }, - }; - - request.get(url, options, userReadCallback); - let result = { - success: true, - }; - function userReadCallback(err, data) { - if (err) { - result.success = false; - } else { - let response = JSON.parse(data.body); - if (response.responseCode === HTTP_STATUS_CODE["ok"].code) { - result["data"] = response.result; - result.data = _.omit(response.result, [ - "response.email", - "response.maskedEmail", - "response.maskedPhone", - "response.recoveryEmail", - "response.phone", - "response.lastName", - "response.prevUsedPhone", - "response.prevUsedEmail", - "response.recoveryPhone", - ]); - } else { - result.success = false; - } + const options = { + headers : { + "content-type": "application/json", + "x-authenticated-user-token" : token + } + }; + + request.get(url,options,userReadCallback); + let result = { + success : true + }; + function userReadCallback(err, data) { + + if (err) { + result.success = false; + } else { + + let response = JSON.parse(data.body); + if( response.responseCode === HTTP_STATUS_CODE['ok'].code ) { + result["data"] = _.omit(response.result, [ + "response.email", + "response.maskedEmail", + "response.maskedPhone", + "response.recoveryEmail", + "response.phone", + "response.prevUsedPhone", + "response.prevUsedEmail", + "response.recoveryPhone", + ]); + } else { + result.success = false; + } + + } + + return resolve(result); + } + setTimeout(function () { + return resolve (result = { + success : false + }); + }, CONSTANTS.common.SERVER_TIME_OUT); + + } catch (error) { + return reject(error); } + }) +} - return resolve(result); - } - setTimeout(function () { - return resolve( - (result = { - success: false, - }) - ); - }, CONSTANTS.common.SERVER_TIME_OUT); - } catch (error) { - return reject(error); - } - }); -}; /** - * - * @function - * @name locationSearch - * @param {object} filterData - location search filter object. - * @param {Boolean} formatResult - format result or not. - * @returns {Promise} returns a promise. - */ - -const locationSearch = function (filterData, formatResult = false) { + * + * @function + * @name locationSearch + * @param {object} filterData - location search filter object. + * @param {Boolean} formatResult - format result or not. + * @returns {Promise} returns a promise. +*/ + +const locationSearch = function ( filterData, formatResult = false ) { return new Promise(async (resolve, reject) => { - try { - let bodyData = {}; - bodyData["request"] = {}; - bodyData["request"]["filters"] = filterData; - const url = userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; - const options = { - headers: { - "content-type": "application/json", - }, - json: bodyData, - }; - - request.post(url, options, requestCallback); - - let result = { - success: true, - }; - - function requestCallback(err, data) { - if (err) { - result.success = false; - } else { - let response = data.body; - - if ( - response.responseCode === CONSTANTS.common.OK && - response.result && - response.result.response && - response.result.response.length > 0 - ) { - if (formatResult) { - let entityResult = new Array(); - response.result.response.map((entityData) => { - let data = {}; - data._id = entityData.id; - data.entityType = entityData.type; - data.metaInformation = {}; - data.metaInformation.name = entityData.name; - data.metaInformation.externalId = entityData.code; - data.registryDetails = {}; - data.registryDetails.locationId = entityData.id; - data.registryDetails.code = entityData.code; - entityResult.push(data); - }); - result["data"] = entityResult; - result["count"] = response.result.count; + try { + + let bodyData={}; + bodyData["request"] = {}; + bodyData["request"]["filters"] = filterData; + const url = + userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; + const options = { + headers : { + "content-type": "application/json" + }, + json : bodyData + }; + + request.post(url,options,requestCallback); + + let result = { + success : true + }; + + function requestCallback(err, data) { + if (err) { + result.success = false; } else { - result["data"] = response.result.response; - result["count"] = response.result.count; + let response = data.body; + + if( response.responseCode === CONSTANTS.common.OK && + response.result && + response.result.response && + response.result.response.length > 0 + ) { + if ( formatResult ) { + let entityResult =new Array; + response.result.response.map(entityData => { + let data = {}; + data._id = entityData.id; + data.entityType = entityData.type; + data.metaInformation = {}; + data.metaInformation.name = entityData.name; + data.metaInformation.externalId = entityData.code + data.registryDetails = {}; + data.registryDetails.locationId = entityData.id; + data.registryDetails.code = entityData.code; + entityResult.push(data); + }); + result["data"] = entityResult; + result["count"] = response.result.count; + } else { + result["data"] = response.result.response; + result["count"] = response.result.count; + } + + } else { + result.success = false; + } } - } else { - result.success = false; - } + return resolve(result); } - return resolve(result); - } - setTimeout(function () { - return resolve( - (result = { - success: false, - }) - ); - }, CONSTANTS.common.SERVER_TIME_OUT); - } catch (error) { - return reject(error); - } - }); -}; + setTimeout(function () { + return resolve (result = { + success : false + }); + }, CONSTANTS.common.SERVER_TIME_OUT); + + } catch (error) { + return reject(error); + } + }) +} /** - * get Parent Entities of an entity. - * @method - * @name getParentEntities - * @param {String} entityId - entity id - * @returns {Array} - parent entities. - */ + * get Parent Entities of an entity. + * @method + * @name getParentEntities + * @param {String} entityId - entity id + * @returns {Array} - parent entities. +*/ -async function getParentEntities(entityId, iteration = 0, parentEntities) { - if (iteration == 0) { - parentEntities = []; - } +async function getParentEntities( entityId, iteration = 0, parentEntities ) { - let filterQuery = { - id: entityId, - }; + if ( iteration == 0 ) { + parentEntities = []; + } - let entityDetails = await locationSearch(filterQuery); - if (!entityDetails.success) { - return parentEntities; - } else { - let entityData = entityDetails.data[0]; - if (iteration > 0) parentEntities.push(entityData); - if (entityData.parentId) { - iteration = iteration + 1; - entityId = entityData.parentId; - await getParentEntities(entityId, iteration, parentEntities); + let filterQuery = { + "id" : entityId + }; + + let entityDetails = await locationSearch(filterQuery); + if ( !entityDetails.success ) { + return parentEntities; + } else { + + let entityData = entityDetails.data[0]; + if ( iteration > 0 ) parentEntities.push(entityData); + if ( entityData.parentId ) { + iteration = iteration + 1; + entityId = entityData.parentId; + await getParentEntities(entityId, iteration, parentEntities); + } } - } - return parentEntities; + return parentEntities; + } /** - * get user profileData without token. - * @method - * @name profileReadPrivate - * @param {String} userId - user Id - * @returns {JSON} - User profile details - */ + * get user profileData without token. + * @method + * @name profileReadPrivate + * @param {String} userId - user Id + * @returns {JSON} - User profile details +*/ const profileReadPrivate = function (userId) { - return new Promise(async (resolve, reject) => { - try { - // <--- Important : This url endpoint is private do not use it for regular workflows ---> - let url = - userServiceUrl + CONSTANTS.endpoints.USER_READ_PRIVATE + "/" + userId; - const options = { - headers: { - "content-type": "application/json", - }, - }; - request.get(url, options, userReadCallback); - let result = { - success: true, - }; - function userReadCallback(err, data) { - if (err) { - result.success = false; - } else { - let response = JSON.parse(data.body); - if (response.responseCode === HTTP_STATUS_CODE["ok"].code) { - result["data"] = response.result; - result.data = _.omit(response.result, [ - "response.email", - "response.maskedEmail", - "response.maskedPhone", - "response.recoveryEmail", - "response.phone", - "response.lastName", - "response.prevUsedPhone", - "response.prevUsedEmail", - "response.recoveryPhone", - ]); - } else { - result.success = false; - } + return new Promise(async (resolve, reject) => { + try { + // <--- Important : This url endpoint is private do not use it for regular workflows ---> + let url = userServiceUrl + CONSTANTS.endpoints.USER_READ_PRIVATE + "/" + userId; + const options = { + headers : { + "content-type": "application/json" + } + }; + request.get(url,options,userReadCallback); + let result = { + success : true + }; + function userReadCallback(err, data) { + if (err) { + result.success = false; + } else { + + let response = JSON.parse(data.body); + if( response.responseCode === HTTP_STATUS_CODE['ok'].code ) { + result["data"] = response.result; + } else { + result.success = false; + } + + } + return resolve(result); + } + setTimeout(function () { + return resolve (result = { + success : false + }); + }, CONSTANTS.common.SERVER_TIME_OUT); + + } catch (error) { + return reject(error); } - return resolve(result); - } - setTimeout(function () { - return resolve( - (result = { - success: false, - }) - ); - }, CONSTANTS.common.SERVER_TIME_OUT); - } catch (error) { - return reject(error); - } - }); -}; + }) +} module.exports = { - profile: profile, - locationSearch: locationSearch, - getParentEntities: getParentEntities, - profileReadPrivate: profileReadPrivate, + profile : profile, + locationSearch : locationSearch, + getParentEntities : getParentEntities, + profileReadPrivate : profileReadPrivate }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index eeac91f8..89c4b340 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -8,47 +8,39 @@ // Dependencies const coreService = require(GENERICS_FILES_PATH + "/services/core"); -const libraryCategoriesHelper = require(MODULES_BASE_PATH + - "/library/categories/helper"); -const projectTemplatesHelper = require(MODULES_BASE_PATH + - "/project/templates/helper"); -const projectTemplateTasksHelper = require(MODULES_BASE_PATH + - "/project/templateTasks/helper"); -const { v4: uuidv4 } = require("uuid"); +const libraryCategoriesHelper = require(MODULES_BASE_PATH + "/library/categories/helper"); +const projectTemplatesHelper = require(MODULES_BASE_PATH + "/project/templates/helper"); +const projectTemplateTasksHelper = require(MODULES_BASE_PATH + "/project/templateTasks/helper"); +const { v4: uuidv4 } = require('uuid'); const surveyService = require(GENERICS_FILES_PATH + "/services/survey"); const reportService = require(GENERICS_FILES_PATH + "/services/report"); const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); -const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + - "/projectCategories"); -const projectTemplateQueries = require(DB_QUERY_BASE_PATH + - "/projectTemplates"); -const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + - "/projectTemplateTask"); +const projectCategoriesQueries = require(DB_QUERY_BASE_PATH + "/projectCategories"); +const projectTemplateQueries = require(DB_QUERY_BASE_PATH + "/projectTemplates"); +const projectTemplateTaskQueries = require(DB_QUERY_BASE_PATH + "/projectTemplateTask"); const kafkaProducersHelper = require(GENERICS_FILES_PATH + "/kafka/producers"); const removeFieldsFromRequest = ["submissionDetails"]; const programsQueries = require(DB_QUERY_BASE_PATH + "/programs"); const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); const solutionsHelper = require(MODULES_BASE_PATH + "/solutions/helper"); -const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + - "/certificateTemplates"); -const certificateService = require(GENERICS_FILES_PATH + - "/services/certificate"); -const certificateValidationsHelper = require(MODULES_BASE_PATH + - "/certificateValidations/helper"); -const _ = require("lodash"); - +const certificateTemplateQueries = require(DB_QUERY_BASE_PATH + "/certificateTemplates"); +const certificateService = require(GENERICS_FILES_PATH + "/services/certificate"); +const certificateValidationsHelper = require(MODULES_BASE_PATH + "/certificateValidations/helper"); +const _ = require("lodash"); const programUsersQueries = require(DB_QUERY_BASE_PATH + "/programUsers"); - +const telemetryEventOnOff = process.env.TELEMETRY_ON_OFF /** - * UserProjectsHelper - * @class - */ + * UserProjectsHelper + * @class +*/ module.exports = class UserProjectsHelper { - /** - * userDelete function to delete users Data. + + + /** + * deleteUserPIIData function to delete users Data. * @method - * @name userDelete + * @name deleteUserPIIData * @param {userDeleteEvent} - userDeleteEvent message object * { "eid": "BE_JOB_REQUEST", @@ -99,567 +91,540 @@ module.exports = class UserProjectsHelper { } * @returns {Promise} success Data. */ - static userDelete(userDeleteEvent) { - return new Promise(async (resolve, reject) => { - let userId = userDeleteEvent.edata.userId; - let userProfileUpdateData = []; - let userProjectData = await projectQueries.projectDocument( - { - userId: userId, - userProfile: { $exists: true }, - }, - ["userProfile"], - "none" - ); - if (userProjectData.length === 0) { - return resolve({ success: false }); - } - if (userProjectData.length > 0) { - userProjectData.forEach((userProfile) => { - let updateProfile = { - updateOne: { - filter: { _id: userProfile._id }, - update: { + static deleteUserPIIData(userDeleteEvent) { + return new Promise(async (resolve, reject) => { + try{ + let userId = userDeleteEvent.edata.userId; + let filter = { + userId: userId, + } + let updateProfile = { $set: { - "userProfile.firstName": CONSTANTS.common.DELETED_USER, + "userProfile.firstName": CONSTANTS.common.DELETED_USER, }, $unset: { - "userProfile.email": 1, - "userProfile.maskedEmail": 1, - "userProfile.maskedPhone": 1, - "userProfile.recoveryEmail": 1, - "userProfile.phone": 1, - "userProfile.lastName": 1, - "userProfile.prevUsedPhone": 1, - "userProfile.prevUsedEmail": 1, - "userProfile.recoveryPhone": 1, + "userProfile.email": 1, + "userProfile.maskedEmail": 1, + "userProfile.maskedPhone": 1, + "userProfile.recoveryEmail": 1, + "userProfile.phone": 1, + "userProfile.lastName": 1, + "userProfile.prevUsedPhone": 1, + "userProfile.prevUsedEmail": 1, + "userProfile.recoveryPhone": 1, }, - }, - multi: true, - }, - }; - userProfileUpdateData.push(updateProfile); + }; + let deleteUserPIIDataResult = await projectQueries.updateMany(filter, updateProfile) + if (deleteUserPIIDataResult && deleteUserPIIDataResult.nModified > 0) { + if(telemetryEventOnOff !== CONSTANTS.common.OFF){ + /** + * Telemetry Raw Event + * {"eid":"","ets":1700188609568,"ver":"3.0","mid":"e55a91cd-7964-46bc-b756-18750787fb32","actor":{},"context":{"channel":"","pdata":{"id":"projectservice","pid":"manage-learn","ver":"7.0.0"},"env":"","cdata":[{"id":"adf3b621-619b-4195-a82d-d814eecdb21f","type":"Request"}],"rollup":{}},"object":{},"edata":{}} + */ + let rawEvent = await UTILS.generateTelemetryEventSkeletonStructure(); + rawEvent.eid = CONSTANTS.common.AUDIT; + rawEvent.context.channel = userDeleteEvent.context.channel; + rawEvent.context.env = CONSTANTS.common.USER; + rawEvent.edata.state = CONSTANTS.common.DELETE_STATE; + rawEvent.edata.type = CONSTANTS.common.USER_DELETE_TYPE; + rawEvent.edata.props = []; + let userObject = { + id: userId, + type: CONSTANTS.common.USER, + }; + rawEvent.actor = userObject; + rawEvent.object = userObject; + rawEvent.context.pdata.pid = `${process.env.ID}.${CONSTANTS.common.USER_DELETE_MODULE}` + + let telemetryEvent = await UTILS.generateTelemetryEvent(rawEvent); + telemetryEvent.lname = CONSTANTS.common.TELEMTRY_EVENT_LOGGER; + telemetryEvent.level = CONSTANTS.common.INFO_LEVEL + + await kafkaProducersHelper.pushTelemetryEventToKafka(telemetryEvent); + } + return resolve({ success: true }); + }else{ + return resolve({ success: true }); + } + } catch (error) { + return reject(error); + } }); - } - let updateUserProfile = await projectQueries.bulkUpdate( - userProfileUpdateData - ); - if (updateUserProfile) { - /** - * Telemetry Raw Event - * {"eid":"","ets":1700188609568,"ver":"3.0","mid":"e55a91cd-7964-46bc-b756-18750787fb32","actor":{},"context":{"channel":"","pdata":{"id":"projectservice","pid":"manage-learn","ver":"7.0.0"},"env":"","cdata":[{"id":"adf3b621-619b-4195-a82d-d814eecdb21f","type":"Request"}],"rollup":{}},"object":{},"edata":{}} - */ - let rawEvent = await UTILS.getTelemetryEvent(); - rawEvent.eid = CONSTANTS.common.AUDIT; - rawEvent.context.channel = userDeleteEvent.context.channel; - rawEvent.context.env = "User"; - rawEvent.edata.state = CONSTANTS.common.DELETE_STATE; - rawEvent.edata.type = CONSTANTS.common.USER_DELETE_TYPE; - rawEvent.edata.props = []; - let userObject = { - id: userId, - type: "User", - }; - rawEvent.actor = userObject; - rawEvent.object = userObject; - - let telemetryEvent = { - timestamp: new Date(), - msg: JSON.stringify(rawEvent), - lname: CONSTANTS.common.TELEMTRY_EVENT_LOGGER, - tname: "", - level: CONSTANTS.common.INFO_LEVEL, - HOSTNAME: "", - "application.home": "", - }; - await kafkaProducersHelper.pushTelemetryEventToKafka(telemetryEvent); - return resolve({ success: true }); - } - }); - } - - /** - * Projects boolean data. - * @method - * @name booleanData - * @returns {Array} Boolean data. - */ - - static booleanData() { - const projectsSchema = schemas["projects"].schema; - const projectSchemaKey = Object.keys(projectsSchema); - - let booleanProjects = []; - - projectSchemaKey.forEach((projectSchema) => { - const currentSchema = projectsSchema[projectSchema]; + } - if ( - currentSchema.hasOwnProperty("default") && - typeof currentSchema.default === "boolean" - ) { - booleanProjects.push(projectSchema); - } - }); + /** + * Projects boolean data. + * @method + * @name booleanData + * @returns {Array} Boolean data. + */ - return booleanProjects; - } + static booleanData() { - /** - * Projects object id field. - * @method - * @name mongooseIdData - * @returns {Array} Projects object id field. - */ + const projectsSchema = schemas["projects"].schema; + const projectSchemaKey = Object.keys(projectsSchema); - static mongooseIdData() { - const projectsSchema = schemas["projects"].schema; - const projectSchemaKey = Object.keys(projectsSchema); + let booleanProjects = []; - let mongooseIds = []; + projectSchemaKey.forEach(projectSchema => { + const currentSchema = projectsSchema[projectSchema]; - projectSchemaKey.forEach((projectSchema) => { - const currentSchemaType = projectsSchema[projectSchema]; + if ( + currentSchema.hasOwnProperty('default') && + typeof currentSchema.default === "boolean" + ) { + booleanProjects.push(projectSchema); + } + }); - if (currentSchemaType === "ObjectId") { - mongooseIds.push(projectSchema); - } - }); + return booleanProjects; + } - return mongooseIds; - } + /** + * Projects object id field. + * @method + * @name mongooseIdData + * @returns {Array} Projects object id field. + */ - /** - * Sync project. - * @method - * @name sync - * @param {String} projectId - id of the project. - * @param {String} lastDownloadedAt - last downloaded at time. - * @param {Object} data - body data. - * @param {String} userId - Logged in user id. - * @param {String} userToken - User token. - * @param {String} [appName = ""] - App Name. - * @param {String} [appVersion = ""] - App Version. - * @returns {Object} Project created information. - */ + static mongooseIdData() { - static sync( - projectId, - lastDownloadedAt, - data, - userId, - userToken, - appName = "", - appVersion = "" - ) { - return new Promise(async (resolve, reject) => { - try { - const userProject = await projectQueries.projectDocument( - { - _id: projectId, - userId: userId, - }, - [ - "_id", - "tasks", - "programInformation._id", - "solutionInformation._id", - "solutionInformation.externalId", - "entityInformation._id", - "lastDownloadedAt", - "appInformation", - "status", - ] - ); - - if (!userProject.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND, - }; - } + const projectsSchema = schemas["projects"].schema; + const projectSchemaKey = Object.keys(projectsSchema); - if ( - userProject[0].lastDownloadedAt.toISOString() !== lastDownloadedAt - ) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.USER_ALREADY_SYNC, - }; - } + let mongooseIds = []; - if (userProject[0].status == CONSTANTS.common.SUBMITTED_STATUS) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: - CONSTANTS.apiResponses.FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED, - }; - } + projectSchemaKey.forEach(projectSchema => { - const projectsModel = Object.keys(schemas["projects"].schema); + const currentSchemaType = projectsSchema[projectSchema]; - let keysToRemoveFromUpdation = [ - "userRoleInformation", - "userProfile", - "certificate", - ]; - keysToRemoveFromUpdation.forEach((key) => { - if (data[key]) delete data[key]; + if (currentSchemaType === "ObjectId") { + mongooseIds.push(projectSchema); + } }); - let updateProject = {}; - let projectData = await _projectData(data); - if (projectData && projectData.success == true) { - updateProject = _.merge(updateProject, projectData.data); - } - let createNewProgramAndSolution = false; - let solutionExists = false; - - if (data.programId && data.programId !== "") { - // Check if program already existed in project and if its not an existing program. - if (!userProject[0].programInformation) { - createNewProgramAndSolution = true; - } else if ( - userProject[0].programInformation && - userProject[0].programInformation._id && - userProject[0].programInformation._id.toString() !== data.programId - ) { - // Not an existing program. - - solutionExists = true; - } - } else if (data.programName) { - if (!userProject[0].solutionInformation) { - createNewProgramAndSolution = true; - } else { - solutionExists = true; - // create new program using current name and add existing solution and remove program from it. - } - } + return mongooseIds; + } - let addOrUpdateEntityToProject = false; + /** + * Sync project. + * @method + * @name sync + * @param {String} projectId - id of the project. + * @param {String} lastDownloadedAt - last downloaded at time. + * @param {Object} data - body data. + * @param {String} userId - Logged in user id. + * @param {String} userToken - User token. + * @param {String} [appName = ""] - App Name. + * @param {String} [appVersion = ""] - App Version. + * @returns {Object} Project created information. + */ - if (data.entityId) { - // If entity is not present in project or new entity is updated. - if ( - !userProject[0].entityInformation || - (userProject[0].entityInformation && - userProject[0].entityInformation._id !== data.entityId) - ) { - addOrUpdateEntityToProject = true; - } - } + static sync(projectId, lastDownloadedAt, data, userId, userToken, appName = "", appVersion = "") { + return new Promise(async (resolve, reject) => { + try { + + const userProject = await projectQueries.projectDocument({ + _id: projectId, + userId: userId + }, [ + "_id", + "tasks", + "programInformation._id", + "solutionInformation._id", + "solutionInformation.externalId", + "entityInformation._id", + "lastDownloadedAt", + "appInformation", + "status" + ]); + + if (!userProject.length > 0) { + + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND + }; + } - if (addOrUpdateEntityToProject) { - let entityInformation = await _entitiesInformation([data.entityId]); + if (userProject[0].lastDownloadedAt.toISOString() !== lastDownloadedAt) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.USER_ALREADY_SYNC + }; + } - if (!entityInformation.success) { - return resolve(entityInformation); - } + if ( userProject[0].status == CONSTANTS.common.SUBMITTED_STATUS ) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.FAILED_TO_SYNC_PROJECT_ALREADY_SUBMITTED + }; + } - updateProject["entityInformation"] = entityInformation.data[0]; - updateProject.entityId = entityInformation.data[0]._id; - } + const projectsModel = Object.keys(schemas["projects"].schema); + + let keysToRemoveFromUpdation = ["userRoleInformation","userProfile","certificate"] + keysToRemoveFromUpdation.forEach( key => { + if (data[key])delete data[key]; + }) + + let updateProject = {}; + let projectData = await _projectData(data); + if (projectData && projectData.success == true) { + updateProject = _.merge(updateProject, projectData.data); + } + let createNewProgramAndSolution = false; + let solutionExists = false; + + if (data.programId && data.programId !== "") { + + // Check if program already existed in project and if its not an existing program. + if (!userProject[0].programInformation) { + createNewProgramAndSolution = true; + } else if ( + userProject[0].programInformation && + userProject[0].programInformation._id && + userProject[0].programInformation._id.toString() !== data.programId + ) { + // Not an existing program. + + solutionExists = true; + } + + } else if (data.programName) { + + if (!userProject[0].solutionInformation) { + createNewProgramAndSolution = true; + } else { + solutionExists = true; + // create new program using current name and add existing solution and remove program from it. + } + } - if (createNewProgramAndSolution || solutionExists) { - let programAndSolutionInformation = - await this.createProgramAndSolution( - data.programId, - data.programName, - updateProject.entityId ? [updateProject.entityId] : "", - userToken, - userProject[0].solutionInformation && - userProject[0].solutionInformation._id - ? userProject[0].solutionInformation._id - : "" - ); + let addOrUpdateEntityToProject = false; + + if (data.entityId) { + + // If entity is not present in project or new entity is updated. + if ( + !userProject[0].entityInformation || + ( + userProject[0].entityInformation && + userProject[0].entityInformation._id !== data.entityId + ) + ) { + addOrUpdateEntityToProject = true; + } + } + + if (addOrUpdateEntityToProject) { - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } + let entityInformation = + await _entitiesInformation([data.entityId]); - if (solutionExists) { - let updateProgram = await surveyService.removeSolutionsFromProgram( - userToken, - userProject[0].programInformation._id, - [userProject[0].solutionInformation._id] - ); + if (!entityInformation.success) { + return resolve(entityInformation); + } - if (!updateProgram.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROGRAM_NOT_UPDATED, - }; - } - } + updateProject["entityInformation"] = entityInformation.data[0]; + updateProject.entityId = entityInformation.data[0]._id; + } + + if (createNewProgramAndSolution || solutionExists) { + + let programAndSolutionInformation = + await this.createProgramAndSolution( + data.programId, + data.programName, + updateProject.entityId ? [updateProject.entityId] : "", + userToken, + userProject[0].solutionInformation && userProject[0].solutionInformation._id ? + userProject[0].solutionInformation._id : "" + ); + + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + + if (solutionExists) { + + let updateProgram = + await surveyService.removeSolutionsFromProgram( + userToken, + userProject[0].programInformation._id, + [userProject[0].solutionInformation._id] + ); + + if (!updateProgram.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.PROGRAM_NOT_UPDATED + } + } + } + + updateProject = + _.merge(updateProject, programAndSolutionInformation.data); + } - updateProject = _.merge( - updateProject, - programAndSolutionInformation.data - ); - } + let booleanData = this.booleanData(schemas["projects"].schema); + let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); - let booleanData = this.booleanData(schemas["projects"].schema); - let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); + if (data.tasks) { - if (data.tasks) { - let taskReport = {}; + let taskReport = {}; - updateProject.tasks = await _projectTask(data.tasks); + updateProject.tasks = await _projectTask( + data.tasks + ); - if (userProject[0].tasks && userProject[0].tasks.length > 0) { - updateProject.tasks.forEach((task) => { - task.updatedBy = userId; - task.updatedAt = new Date(); + if ( + userProject[0].tasks && + userProject[0].tasks.length > 0 + ) { + + updateProject.tasks.forEach(task => { + + task.updatedBy = userId; + task.updatedAt = new Date(); + + let taskIndex = + userProject[0].tasks.findIndex( + projectTask => projectTask._id === task._id + ); + + if (taskIndex < 0) { + userProject[0].tasks.push( + task + ); + } else { + + let keepFieldsFromTask = ["observationInformation", "submissions"]; + + removeFieldsFromRequest.forEach((removeField) => { + delete userProject[0].tasks[taskIndex][removeField]; + }); + + keepFieldsFromTask.forEach((field) => { + if ( userProject[0].tasks[taskIndex][field] ){ + task[field] = userProject[0].tasks[taskIndex][field]; + } + }); + + userProject[0].tasks[taskIndex] = task; + } + }); + + updateProject.tasks = userProject[0].tasks; + } + + taskReport.total = updateProject.tasks.length; + + updateProject.tasks.forEach(task => { + //consider tasks where isDeleted is false. + if ( task.isDeleted == false ) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + } else { + taskReport.total = taskReport.total - 1; + } + + }); + + updateProject["taskReport"] = taskReport; + } - let taskIndex = userProject[0].tasks.findIndex( - (projectTask) => projectTask._id === task._id - ); + Object.keys(data).forEach(updateData => { + if ( + !updateProject[updateData] && + projectsModel.includes(updateData) + ) { - if (taskIndex < 0) { - userProject[0].tasks.push(task); - } else { - let keepFieldsFromTask = [ - "observationInformation", - "submissions", - ]; + if (booleanData.includes(updateData)) { - removeFieldsFromRequest.forEach((removeField) => { - delete userProject[0].tasks[taskIndex][removeField]; - }); + updateProject[updateData] = + UTILS.convertStringToBoolean(data[updateData]); - keepFieldsFromTask.forEach((field) => { - if (userProject[0].tasks[taskIndex][field]) { - task[field] = userProject[0].tasks[taskIndex][field]; - } + } else if (mongooseIdData.includes(updateData)) { + updateProject[updateData] = ObjectId(data[updateData]); + } else { + updateProject[updateData] = data[updateData]; + } + } }); - userProject[0].tasks[taskIndex] = task; - } - }); - - updateProject.tasks = userProject[0].tasks; - } - - taskReport.total = updateProject.tasks.length; + updateProject.updatedBy = userId; + updateProject.updatedAt = new Date(); - updateProject.tasks.forEach((task) => { - //consider tasks where isDeleted is false. - if (task.isDeleted == false) { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - } else { - taskReport.total = taskReport.total - 1; - } - }); + if (!userProject[0].appInformation) { + updateProject["appInformation"] = {}; - updateProject["taskReport"] = taskReport; - } + if (appName !== "") { + updateProject["appInformation"]["appName"] = appName; + } - Object.keys(data).forEach((updateData) => { - if ( - !updateProject[updateData] && - projectsModel.includes(updateData) - ) { - if (booleanData.includes(updateData)) { - updateProject[updateData] = UTILS.convertStringToBoolean( - data[updateData] - ); - } else if (mongooseIdData.includes(updateData)) { - updateProject[updateData] = ObjectId(data[updateData]); - } else { - updateProject[updateData] = data[updateData]; - } - } - }); + if (appVersion !== "") { + updateProject["appInformation"]["appVersion"] = appVersion; + } + } - updateProject.updatedBy = userId; - updateProject.updatedAt = new Date(); + if ( data.status && data.status !== "" ) { + updateProject.status = UTILS.convertProjectStatus(data.status); + } + + if ( data.status == CONSTANTS.common.COMPLETED_STATUS || data.status == CONSTANTS.common.SUBMITTED_STATUS ) { + updateProject.completedDate = new Date(); + } + + let projectUpdated = + await projectQueries.findOneAndUpdate( + { + _id: userProject[0]._id + }, + { + $set: updateProject + }, { + new: true + } + ); - if (!userProject[0].appInformation) { - updateProject["appInformation"] = {}; + if (!projectUpdated._id) { + throw { + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_UPDATED, + status: HTTP_STATUS_CODE['bad_request'].status + } + } + + // push project details to kafka + await kafkaProducersHelper.pushProjectToKafka(projectUpdated); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, + data : { + programId : + projectUpdated.programInformation && projectUpdated.programInformation._id ? + projectUpdated.programInformation._id : "", + hasAcceptedTAndC : projectUpdated.hasAcceptedTAndC ? projectUpdated.hasAcceptedTAndC : false + } + }); - if (appName !== "") { - updateProject["appInformation"]["appName"] = appName; - } + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); + } + }) + } - if (appVersion !== "") { - updateProject["appInformation"]["appVersion"] = appVersion; - } - } + /** + * Program and solution information + * @method + * @name createProgramAndSolution + * @param {String} entityId - entity id. + * @param {String} userToken - Logged in user token. + * @param {String} [ programId = "" ] - Program Id. + * @param {String} [ programName = "" ] - Program Name. + * @returns {Object} Created program and solution data. + */ - if (data.status && data.status !== "") { - updateProject.status = UTILS.convertProjectStatus(data.status); - } + static createProgramAndSolution( + programId = "", + programName = "", + entities, + userToken, + solutionId, + isATargetedSolution = "" + ) { + return new Promise(async (resolve, reject) => { + try { + + let result = {}; + + let programAndSolutionData = { + type: CONSTANTS.common.IMPROVEMENT_PROJECT, + subType: CONSTANTS.common.IMPROVEMENT_PROJECT, + isReusable: false, + solutionId: solutionId, + entities: entities + }; - if ( - data.status == CONSTANTS.common.COMPLETED_STATUS || - data.status == CONSTANTS.common.SUBMITTED_STATUS - ) { - updateProject.completedDate = new Date(); - } + if (programName !== "") { + programAndSolutionData["programName"] = programName; + } - let projectUpdated = await projectQueries.findOneAndUpdate( - { - _id: userProject[0]._id, - }, - { - $set: updateProject, - }, - { - new: true, - } - ); + if (programId !== "") { + programAndSolutionData["programId"] = programId; + } - if (!projectUpdated._id) { - throw { - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_UPDATED, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } + let solutionAndProgramCreation = + await coreService.createUserProgramAndSolution( + programAndSolutionData, + userToken, + isATargetedSolution + ); + + if (!solutionAndProgramCreation.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.SOLUTION_PROGRAMS_NOT_CREATED + }; + } - // push project details to kafka - await kafkaProducersHelper.pushProjectToKafka(projectUpdated); + result.solutionInformation = _.pick( + solutionAndProgramCreation.data.solution, + ["name", "externalId", "description", "_id", "entityType", "certificateTemplateId"] + ); + + result.solutionInformation._id = + ObjectId(result.solutionInformation._id); - return resolve({ - success: true, - message: CONSTANTS.apiResponses.USER_PROJECT_UPDATED, - data: { - programId: - projectUpdated.programInformation && - projectUpdated.programInformation._id - ? projectUpdated.programInformation._id - : "", - hasAcceptedTAndC: projectUpdated.hasAcceptedTAndC - ? projectUpdated.hasAcceptedTAndC - : false, - }, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, - }); - } - }); - } + result["solutionId"] = ObjectId(result.solutionInformation._id); + result["solutionExternalId"] = result.solutionInformation.externalId; - /** - * Program and solution information - * @method - * @name createProgramAndSolution - * @param {String} entityId - entity id. - * @param {String} userToken - Logged in user token. - * @param {String} [ programId = "" ] - Program Id. - * @param {String} [ programName = "" ] - Program Name. - * @returns {Object} Created program and solution data. - */ + result.programInformation = _.pick( + solutionAndProgramCreation.data.program, + ["_id", "name", "externalId", "description", "isAPrivateProgram"] + ); - static createProgramAndSolution( - programId = "", - programName = "", - entities, - userToken, - solutionId, - isATargetedSolution = "" - ) { - return new Promise(async (resolve, reject) => { - try { - let result = {}; - - let programAndSolutionData = { - type: CONSTANTS.common.IMPROVEMENT_PROJECT, - subType: CONSTANTS.common.IMPROVEMENT_PROJECT, - isReusable: false, - solutionId: solutionId, - entities: entities, - }; - - if (programName !== "") { - programAndSolutionData["programName"] = programName; - } + result["programId"] = ObjectId(result.programInformation._id); + result["programExternalId"] = result.programInformation.externalId; + result["isAPrivateProgram"] = result.programInformation.isAPrivateProgram; - if (programId !== "") { - programAndSolutionData["programId"] = programId; - } + result.programInformation._id = + ObjectId(result.programInformation._id); - let solutionAndProgramCreation = - await coreService.createUserProgramAndSolution( - programAndSolutionData, - userToken, - isATargetedSolution - ); - - if (!solutionAndProgramCreation.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.SOLUTION_PROGRAMS_NOT_CREATED, - }; - } + if( solutionAndProgramCreation.data.parentSolutionInformation ){ + result["link"] = solutionAndProgramCreation.data.parentSolutionInformation.link ? solutionAndProgramCreation.data.parentSolutionInformation.link : ""; + } - result.solutionInformation = _.pick( - solutionAndProgramCreation.data.solution, - [ - "name", - "externalId", - "description", - "_id", - "entityType", - "certificateTemplateId", - ] - ); - - result.solutionInformation._id = ObjectId( - result.solutionInformation._id - ); - - result["solutionId"] = ObjectId(result.solutionInformation._id); - result["solutionExternalId"] = result.solutionInformation.externalId; - - result.programInformation = _.pick( - solutionAndProgramCreation.data.program, - ["_id", "name", "externalId", "description", "isAPrivateProgram"] - ); - - result["programId"] = ObjectId(result.programInformation._id); - result["programExternalId"] = result.programInformation.externalId; - result["isAPrivateProgram"] = - result.programInformation.isAPrivateProgram; - - result.programInformation._id = ObjectId(result.programInformation._id); - - if (solutionAndProgramCreation.data.parentSolutionInformation) { - result["link"] = solutionAndProgramCreation.data - .parentSolutionInformation.link - ? solutionAndProgramCreation.data.parentSolutionInformation.link - : ""; - } + return resolve({ + success: true, + data: result + }); - return resolve({ - success: true, - data: result, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); + } }); - } - }); - } + } - /** + /** * Program and solution information * @method * @name getProgramAndSolutionDetails @@ -693,1093 +658,1002 @@ module.exports = class UserProjectsHelper { } */ - static getProgramAndSolutionDetails(solutionDetails) { - return new Promise(async (resolve, reject) => { - try { - let result = {}; - result.solutionInformation = _.pick(solutionDetails, [ - "name", - "externalId", - "description", - "_id", - "entityType", - "certificateTemplateId", - ]); - - result.solutionInformation._id = ObjectId( - result.solutionInformation._id - ); - - result["solutionId"] = ObjectId(result.solutionInformation._id); - result["solutionExternalId"] = result.solutionInformation.externalId; - - // Adding program informations - result.programInformation = { - _id: solutionDetails.programId, - description: solutionDetails.programDescription, - externalId: solutionDetails.programExternalId, - isAPrivateProgram: solutionDetails.isAPrivateProgram, - name: solutionDetails.programName, - }; - - result["programId"] = ObjectId(result.programInformation._id); - result["programExternalId"] = result.programInformation.externalId; - result["isAPrivateProgram"] = - result.programInformation.isAPrivateProgram; - - result.programInformation._id = ObjectId(result.programInformation._id); - // Get link from parent solution - let solutionData = await solutionsHelper.solutionDocuments( - { - _id: solutionDetails.parentSolutionId, - }, - ["link"] - ); - - result["link"] = - solutionData.length > 0 && solutionData[0].link - ? solutionData[0].link - : ""; - - return resolve({ - success: true, - data: result, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, - }); - } - }); - } + static getProgramAndSolutionDetails( + solutionDetails + ) { + return new Promise(async (resolve, reject) => { + try { - /** - * Project details. - * @method - * @name details - * @param {String} projectId - project id. - * @returns {Object} - */ + let result = {}; + result.solutionInformation = _.pick( + solutionDetails, + ["name", "externalId", "description", "_id", "entityType", "certificateTemplateId"] + ); + + result.solutionInformation._id = + ObjectId(result.solutionInformation._id); + + result["solutionId"] = ObjectId(result.solutionInformation._id); + result["solutionExternalId"] = result.solutionInformation.externalId; + + // Adding program informations + result.programInformation = { + _id: solutionDetails.programId, + description: solutionDetails.programDescription, + externalId: solutionDetails.programExternalId, + isAPrivateProgram: solutionDetails.isAPrivateProgram, + name: solutionDetails.programName + }; + - static details(projectId, userId, userRoleInformation = {}) { - return new Promise(async (resolve, reject) => { - try { - const projectDetails = await projectQueries.projectDocument( - { - _id: projectId, - userId: userId, - }, - "all", - [ - "taskReport", - "projectTemplateId", - "projectTemplateExternalId", - "userId", - "createdBy", - "updatedBy", - "createdAt", - "updatedAt", - "userRoleInformation", - "__v", - ] - ); - - if (!projectDetails.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, - }; - } + result["programId"] = ObjectId(result.programInformation._id); + result["programExternalId"] = result.programInformation.externalId; + result["isAPrivateProgram"] = result.programInformation.isAPrivateProgram; - if (Object.keys(userRoleInformation).length > 0) { - if ( - !projectDetails[0].userRoleInformation || - !Object.keys(projectDetails[0].userRoleInformation).length > 0 - ) { - await projectQueries.findOneAndUpdate( - { - _id: projectId, - }, - { - $set: { userRoleInformation: userRoleInformation }, - } - ); - } - } + result.programInformation._id = + ObjectId(result.programInformation._id); + // Get link from parent solution + let solutionData = await solutionsHelper.solutionDocuments({ + _id: solutionDetails.parentSolutionId, + }, + ["link"]); - let result = await _projectInformation(projectDetails[0]); + result["link"] = ( solutionData.length > 0 && solutionData[0].link ) ? solutionData[0].link : ""; - if (!result.success) { - return resolve(result); - } + return resolve({ + success: true, + data: result + }); - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, - data: result.data, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: [], + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); + } }); - } - }); - } - - /** - * List of library projects. - * @method - * @name projects - * @param pageSize - Size of page. - * @param pageNo - Recent page no. - * @param search - search text. - * @param fieldsArray - array of projections fields. - * @param groupBy - groupBy query. - * @returns {Object} List of library projects. - */ + } - static projects( - query, - pageSize, - pageNo, - searchQuery, - fieldsArray, - groupBy = "" - ) { - return new Promise(async (resolve, reject) => { - try { - let matchQuery = { - $match: query, - }; + /** + * Project details. + * @method + * @name details + * @param {String} projectId - project id. + * @returns {Object} + */ - if (searchQuery && searchQuery.length > 0) { - matchQuery["$match"]["$or"] = searchQuery; - } + static details(projectId, userId,userRoleInformation = {}) { + return new Promise(async (resolve, reject) => { + try { + + const projectDetails = await projectQueries.projectDocument({ + _id: projectId, + userId: userId + }, "all", + [ + "taskReport", + "projectTemplateId", + "projectTemplateExternalId", + "userId", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt", + "userRoleInformation", + "__v" + ]); + + if (!projectDetails.length > 0) { + + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND + } + } - let projection = {}; - fieldsArray.forEach((field) => { - projection[field] = 1; - }); + if (Object.keys(userRoleInformation).length > 0) { - let aggregateData = []; - aggregateData.push(matchQuery); - aggregateData.push({ - $sort: { syncedAt: -1 }, - }); + if (!projectDetails[0].userRoleInformation || !Object.keys(projectDetails[0].userRoleInformation).length > 0) { + await projectQueries.findOneAndUpdate({ + _id: projectId + },{ + $set: {userRoleInformation: userRoleInformation} + }); + } + } - if (groupBy !== "") { - aggregateData.push({ - $group: groupBy, - }); - } else { - aggregateData.push({ - $project: projection, - }); - } + let result = await _projectInformation(projectDetails[0]); + + if (!result.success) { + return resolve(result); + } - aggregateData.push( - { - $facet: { - totalCount: [{ $count: "count" }], - data: [{ $skip: pageSize * (pageNo - 1) }, { $limit: pageSize }], - }, - }, - { - $project: { - data: 1, - count: { - $arrayElemAt: ["$totalCount.count", 0], - }, - }, - } - ); - let result = await projectQueries.getAggregate(aggregateData); + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, + data: result.data + }); - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: { - data: result[0].data, - count: result[0].count ? result[0].count : 0, - }, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: { - data: [], - count: 0, - }, - }); - } - }); - } + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: [] + }); + } + }) + } - /** - * Get tasks from a user project. - * @method - * @name tasks - * @param {String} projectId - Project id. - * @param {Array} taskIds - Array of tasks ids. - * @returns {Object} - return tasks from a project. - */ + /** + * List of library projects. + * @method + * @name projects + * @param pageSize - Size of page. + * @param pageNo - Recent page no. + * @param search - search text. + * @param fieldsArray - array of projections fields. + * @param groupBy - groupBy query. + * @returns {Object} List of library projects. + */ + + static projects(query, pageSize, pageNo, searchQuery, fieldsArray, groupBy = "") { + return new Promise(async (resolve, reject) => { + try { + + let matchQuery = { + $match: query + }; - static tasks(projectId, taskIds) { - return new Promise(async (resolve, reject) => { - try { - let aggregatedData = [ - { - $match: { - _id: ObjectId(projectId), - }, - }, - ]; + if (searchQuery && searchQuery.length > 0) { + matchQuery["$match"]["$or"] = searchQuery; + } - if (taskIds.length > 0) { - let unwindData = { - $unwind: "$tasks", - }; + let projection = {} + fieldsArray.forEach(field => { + projection[field] = 1; + }); - let matchData = { - $match: { - "tasks._id": { $in: taskIds }, - }, - }; + let aggregateData = []; + aggregateData.push(matchQuery); + aggregateData.push({ + $sort : { "syncedAt" : -1 } + }) - let groupData = { - $group: { - _id: "$_id", - tasks: { $push: "$tasks" }, - }, - }; + if (groupBy !== "") { + aggregateData.push({ + $group: groupBy + }); + } else { + aggregateData.push({ + $project: projection + }); + } - aggregatedData.push(unwindData, matchData, groupData); - } + aggregateData.push( + { + $facet: { + "totalCount": [ + { "$count": "count" } + ], + "data": [ + { $skip: pageSize * (pageNo - 1) }, + { $limit: pageSize } + ], + } + }, + { + $project: { + "data": 1, + "count": { + $arrayElemAt: ["$totalCount.count", 0] + } + } + } + ); - let projectData = { - $project: { tasks: 1 }, - }; + let result = + await projectQueries.getAggregate(aggregateData); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data: { + data: result[0].data, + count: result[0].count ? result[0].count : 0 + } + }) + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: { + data: [], + count: 0 + } + }); + } + }) + } - aggregatedData.push(projectData); + /** + * Get tasks from a user project. + * @method + * @name tasks + * @param {String} projectId - Project id. + * @param {Array} taskIds - Array of tasks ids. + * @returns {Object} - return tasks from a project. + */ + + static tasks(projectId, taskIds) { + return new Promise(async (resolve, reject) => { + try { + + let aggregatedData = [{ + $match: { + _id: ObjectId(projectId) + } + }]; + + if (taskIds.length > 0) { + + let unwindData = { + "$unwind": "$tasks" + } + + let matchData = { + "$match": { + "tasks._id": { $in: taskIds } + } + }; + + let groupData = { + "$group": { + "_id": "$_id", + "tasks": { "$push": "$tasks" } + } + } + + aggregatedData.push(unwindData, matchData, groupData); + } - let projects = await projectQueries.getAggregate(aggregatedData); + let projectData = { + "$project": { "tasks": 1 } + } - return resolve({ - success: true, - data: projects, - }); - } catch (error) { - return resolve({ - success: false, - data: [], - }); - } - }); - } + aggregatedData.push(projectData); - /** - * Status of tasks. - * @method - * @name tasksStatus - * @param {String} projectId - Project id. - * @param {Array} taskIds - Tasks ids. - * @returns {Object} - */ + let projects = + await projectQueries.getAggregate(aggregatedData); - static tasksStatus(projectId, taskIds = []) { - return new Promise(async (resolve, reject) => { - try { - let tasks = await this.tasks(projectId, taskIds); - - if (!tasks.success || !tasks.data.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, - }; - } + return resolve({ + success: true, + data: projects + }); - let projectTasks = tasks.data[0].tasks; - let result = []; - - for (let task = 0; task < projectTasks.length; task++) { - let currentTask = projectTasks[task]; - - let data = { - type: currentTask.type, - status: currentTask.status, - _id: currentTask._id, - }; - - if ( - currentTask.type === CONSTANTS.common.ASSESSMENT || - currentTask.type === CONSTANTS.common.OBSERVATION - ) { - let completedSubmissionCount = 0; - - let minNoOfSubmissionsRequired = currentTask.solutionDetails - .minNoOfSubmissionsRequired - ? currentTask.solutionDetails.minNoOfSubmissionsRequired - : CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; - - data["submissionStatus"] = CONSTANTS.common.STARTED; - - // For 4.7 Urgent fix, need to check why observationInformation is not present at task level. - let submissionDetails = {}; - if (currentTask.observationInformation) { - submissionDetails = currentTask.observationInformation; - } else if (currentTask.submissionDetails) { - submissionDetails = currentTask.submissionDetails; - } - - data["submissionDetails"] = submissionDetails; - - if (currentTask.submissions && currentTask.submissions.length > 0) { - let completedSubmissionDoc; - completedSubmissionCount = currentTask.submissions.filter( - (eachSubmission) => - eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS - ).length; - - if (completedSubmissionCount >= minNoOfSubmissionsRequired) { - completedSubmissionDoc = currentTask.submissions.find( - (eachSubmission) => - eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS - ); - data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; - } else { - completedSubmissionDoc = currentTask.submissions.find( - (eachSubmission) => - eachSubmission.status === CONSTANTS.common.STARTED - ); - } - - Object.assign(data["submissionDetails"], completedSubmissionDoc); - } else { - data["submissionDetails"].status = CONSTANTS.common.STARTED; + } catch (error) { + return resolve({ + success: false, + data: [] + }); } - } - - result.push(data); - } - - return resolve({ - success: true, - message: CONSTANTS.apiResponses.TASKS_STATUS_FETCHED, - data: result, - }); - } catch (error) { - return reject({ - success: false, - message: error.message, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - data: [], - }); - } - }); - } - - /** - * Update task. - * @method - * @name updateTask - * @param {String} projectId - Project id. - * @param {String} taskId - Task id. - * @param {Object} updatedData - Update data. - * @returns {Object} - */ + }) + } - static pushSubmissionToTask(projectId, taskId, updatedData) { - return new Promise(async (resolve, reject) => { - try { - let updateSubmission = []; + /** + * Status of tasks. + * @method + * @name tasksStatus + * @param {String} projectId - Project id. + * @param {Array} taskIds - Tasks ids. + * @returns {Object} + */ - let projectDocument = await projectQueries.projectDocument( - { - _id: projectId, - "tasks._id": taskId, - }, - ["tasks"] - ); - - let currentTask = projectDocument[0].tasks.find( - (task) => task._id == taskId - ); - let submissions = - currentTask.submissions && currentTask.submissions.length > 0 - ? currentTask.submissions - : []; - - // if submission array is empty - if (!submissions && !submissions.length > 0) { - updateSubmission.push(updatedData); - } + static tasksStatus(projectId, taskIds = []) { + return new Promise(async (resolve, reject) => { + try { - // submission not exist - let checkSubmissionExist = submissions.findIndex( - (submission) => submission._id == updatedData._id - ); + let tasks = await this.tasks(projectId, taskIds); - if (checkSubmissionExist == -1) { - updateSubmission = submissions; - updateSubmission.push(updatedData); - } else { - //submission exist - submissions[checkSubmissionExist] = updatedData; - updateSubmission = submissions; - } + if (!tasks.success || !tasks.data.length > 0) { - let tasksUpdated = await projectQueries.findOneAndUpdate( - { - _id: projectId, - "tasks._id": taskId, - }, - { - $set: { - "tasks.$.submissions": updateSubmission, - }, - } - ); + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND + }; + } - return resolve(tasksUpdated); - } catch (error) { - return reject(error); - } - }); - } + let projectTasks = tasks.data[0].tasks; + let result = []; - /** - * Solutions details - * @method - * @name solutionDetails - * @param {String} userToken - Logged in user token. - * @param {String} projectId - Project id. - * @param {Array} taskId - Tasks id. - * @returns {Object} - */ + for (let task = 0; task < projectTasks.length; task++) { - static solutionDetails(userToken, projectId, taskId, bodyData = {}) { - return new Promise(async (resolve, reject) => { - try { - let project = await projectQueries.projectDocument( - { - _id: projectId, - "tasks._id": taskId, - }, - [ - "entityInformation._id", - "entityInformation.entityType", - "tasks.type", - "tasks._id", - "tasks.solutionDetails", - "tasks.submissions", - "tasks.observationInformation", - "tasks.externalId", - "programInformation._id", - "projectTemplateId", - ] - ); - if (!project.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND, - }; - } + let currentTask = projectTasks[task]; - let currentTask = project[0].tasks.find((task) => task._id == taskId); - - let solutionDetails = currentTask.solutionDetails; - - let assessmentOrObservationData = {}; - - if ( - project[0].entityInformation && - project[0].entityInformation._id && - project[0].programInformation && - project[0].programInformation._id - ) { - assessmentOrObservationData = { - entityId: project[0].entityInformation._id, - programId: project[0].programInformation._id, - }; - - if (currentTask.observationInformation) { - assessmentOrObservationData = currentTask.observationInformation; - } else { - let assessmentOrObservation = { - token: userToken, - solutionDetails: solutionDetails, - entityId: assessmentOrObservationData.entityId, - programId: assessmentOrObservationData.programId, - project: { - _id: projectId, - taskId: taskId, - }, - }; + let data = { + type: currentTask.type, + status: currentTask.status, + _id: currentTask._id + }; - let assignedAssessmentOrObservation = - solutionDetails.type === CONSTANTS.common.ASSESSMENT - ? await _assessmentDetails(assessmentOrObservation) - : await _observationDetails(assessmentOrObservation, bodyData); + if ( + currentTask.type === CONSTANTS.common.ASSESSMENT || + currentTask.type === CONSTANTS.common.OBSERVATION + ) { - if (!assignedAssessmentOrObservation.success) { - return resolve(assignedAssessmentOrObservation); - } + let completedSubmissionCount = 0; - assessmentOrObservationData = _.merge( - assessmentOrObservationData, - assignedAssessmentOrObservation.data - ); + let minNoOfSubmissionsRequired = currentTask.solutionDetails.minNoOfSubmissionsRequired ? currentTask.solutionDetails.minNoOfSubmissionsRequired : CONSTANTS.common.DEFAULT_SUBMISSION_REQUIRED; - if (!currentTask.solutionDetails.isReusable) { - assessmentOrObservationData["programId"] = - currentTask.solutionDetails.programId; - } + data["submissionStatus"] = CONSTANTS.common.STARTED; - await projectQueries.findOneAndUpdate( - { - _id: projectId, - "tasks._id": taskId, - }, - { - $set: { - "tasks.$.observationInformation": assessmentOrObservationData, - }, - } - ); - } + // For 4.7 Urgent fix, need to check why observationInformation is not present at task level. + let submissionDetails = {}; + if(currentTask.observationInformation) { + submissionDetails = currentTask.observationInformation + } else if (currentTask.submissionDetails) { + submissionDetails = currentTask.submissionDetails + } - assessmentOrObservationData["entityType"] = - project[0].entityInformation.entityType; - } + data["submissionDetails"] = submissionDetails; + + if ( currentTask.submissions && currentTask.submissions.length > 0 ) { - if ( - currentTask.solutionDetails && - !_.isEmpty(currentTask.solutionDetails) - ) { - assessmentOrObservationData.solutionDetails = - currentTask.solutionDetails; - } + let completedSubmissionDoc; + completedSubmissionCount = currentTask.submissions.filter((eachSubmission) => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS).length; - return resolve({ - success: true, - message: CONSTANTS.apiResponses.SOLUTION_DETAILS_FETCHED, - data: assessmentOrObservationData, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, - }); - } - }); - } + if (completedSubmissionCount >= minNoOfSubmissionsRequired ) { + + completedSubmissionDoc = currentTask.submissions.find(eachSubmission => eachSubmission.status === CONSTANTS.common.COMPLETED_STATUS); + data.submissionStatus = CONSTANTS.common.COMPLETED_STATUS; - /** - * Creation of user targeted projects. - * @method - * @name detailsV2 - * @param {String} projectId - project id. - * @param {String} solutionId - solution id. - * @param {String} userId - logged in user id. - * @param {String} userToken - logged in user token. - * @param {Object} bodyData - Requested body data. - * @param {String} [appName = ""] - App name. - * @param {String} [appVersion = ""] - App version. - * @returns {Object} Project details. - */ + } else { - static detailsV2( - projectId, - solutionId, - userId, - userToken, - bodyData, - appName = "", - appVersion = "", - templateId = "" - ) { - return new Promise(async (resolve, reject) => { - try { - let solutionExternalId = ""; - - if (templateId !== "") { - let templateDocuments = await projectTemplateQueries.templateDocument( - { - externalId: templateId, - isReusable: false, - solutionId: { $exists: true }, - }, - ["solutionId", "solutionExternalId"] - ); + completedSubmissionDoc = currentTask.submissions.find(eachSubmission => eachSubmission.status === CONSTANTS.common.STARTED); + } - if (!templateDocuments.length > 0) { - throw { - message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } + Object.assign(data["submissionDetails"],completedSubmissionDoc) - solutionId = templateDocuments[0].solutionId; - solutionExternalId = templateDocuments[0].solutionExternalId; - } + } else { - let userRoleInformation = _.omit(bodyData, [ - "referenceFrom", - "submissions", - "hasAcceptedTAndC", - "link", - ]); - - if (projectId === "") { - // This will check wether the user user is targeted to solution or not based on his userRoleInformation - const targetedSolutionId = - await coreService.checkIfSolutionIsTargetedForUserProfile( - userToken, - userRoleInformation, - solutionId - ); - //based on above api will check for projects wether its is private project or public project - const projectDetails = await projectQueries.projectDocument( - { - solutionId: solutionId, - userId: userId, - isAPrivateProgram: targetedSolutionId.data.isATargetedSolution - ? false - : true, - }, - ["_id"] - ); - if (projectDetails.length > 0) { - projectId = projectDetails[0]._id; - } else { - let isAPrivateSolution = - targetedSolutionId.data.isATargetedSolution === false - ? true - : false; - let solutionDetails = {}; - - if (templateId === "") { - // If solution Id of a private program is passed, fetch solution details - if (isAPrivateSolution && solutionId != "") { - solutionDetails = await solutionsHelper.solutionDocuments( - { - _id: solutionId, - isAPrivateProgram: true, - }, - [ - "name", - "externalId", - "description", - "programId", - "programName", - "programDescription", - "programExternalId", - "isAPrivateProgram", - "projectTemplateId", - "entityType", - "entityTypeId", - "language", - "creator", - ] - ); - if (!solutionDetails.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - }; - } - solutionDetails = solutionDetails[0]; - } else { - solutionDetails = - await coreService.solutionDetailsBasedOnRoleAndLocation( - userToken, - bodyData, - solutionId, - isAPrivateSolution - ); + data["submissionDetails"].status = CONSTANTS.common.STARTED; + } + + } - if ( - !solutionDetails.success || - (solutionDetails.data.data && - !solutionDetails.data.data.length > 0) - ) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: - CONSTANTS.apiResponses.SOLUTION_DOES_NOT_EXISTS_IN_SCOPE, - }; + result.push(data); } - solutionDetails = solutionDetails.data; - } - } else { - solutionDetails = await surveyService.listSolutions([ - solutionExternalId, - ]); - if (!solutionDetails.success) { - throw { - message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } - - solutionDetails = solutionDetails.data[0]; - } - // check for requestForPIIConsent data - let queryData = {}; - queryData["_id"] = solutionDetails.programId; - let programDetails = await programsQueries.programsDocument( - queryData, - ["requestForPIIConsent"] - ); + return resolve({ + success: true, + message: CONSTANTS.apiResponses.TASKS_STATUS_FETCHED, + data: result + }); - // if requestForPIIConsent not there do not call program join - if ( - programDetails.length > 0 && - programDetails[0].hasOwnProperty("requestForPIIConsent") - ) { - // program join API call it will increment the noOfResourcesStarted counter and will make user join program - // before creating any project this api has to called - let programUsers = await programUsersQueries.programUsersDocument( - { - userId: userId, - programId: solutionDetails.programId, - }, - ["_id", "resourcesStarted"] - ); - - if ( - !programUsers.length > 0 || - (programUsers.length > 0 && - programUsers[0].resourcesStarted == false) - ) { - let programJoinBody = {}; - programJoinBody.userRoleInformation = userRoleInformation; - programJoinBody.isResource = true; - programJoinBody.consentShared = true; - let joinProgramData = await coreService.joinProgram( - solutionDetails.programId, - programJoinBody, - userToken - ); - if (!joinProgramData.success) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED, - }); - } - } + } catch (error) { + return reject({ + success: false, + message: error.message, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + data: [] + }); } + }) + } - let projectCreation = await this.userAssignedProjectCreation( - solutionDetails.projectTemplateId, - userId, - userToken - ); + /** + * Update task. + * @method + * @name updateTask + * @param {String} projectId - Project id. + * @param {String} taskId - Task id. + * @param {Object} updatedData - Update data. + * @returns {Object} + */ - if (!projectCreation.success) { - return resolve(projectCreation); - } + static pushSubmissionToTask(projectId, taskId, updatedData) { + return new Promise(async (resolve, reject) => { + try { + + let updateSubmission = []; + + let projectDocument = await projectQueries.projectDocument( + { + _id: projectId, + "tasks._id": taskId + }, [ + "tasks" + ]); + + let currentTask = projectDocument[0].tasks.find(task => task._id == taskId); + let submissions = currentTask.submissions && currentTask.submissions.length > 0 ? currentTask.submissions : [] ; + + // if submission array is empty + if ( !submissions && !submissions.length > 0 ) { + updateSubmission.push(updatedData); + } + + // submission not exist + let checkSubmissionExist = submissions.findIndex(submission => submission._id == updatedData._id); - projectCreation.data["isAPrivateProgram"] = - solutionDetails.isAPrivateProgram; + if ( checkSubmissionExist == -1 ) { - projectCreation.data.programInformation = { - _id: ObjectId(solutionDetails.programId), - externalId: solutionDetails.programExternalId, - description: solutionDetails.programDescription - ? solutionDetails.programDescription - : "", - name: solutionDetails.programName, - }; + updateSubmission = submissions; + updateSubmission.push(updatedData); - projectCreation.data.solutionInformation = { - _id: ObjectId(solutionDetails._id), - externalId: solutionDetails.externalId, - description: solutionDetails.description - ? solutionDetails.description - : "", - name: solutionDetails.name, - }; + } else { + //submission exist + submissions[checkSubmissionExist] = updatedData; + updateSubmission = submissions; + } - projectCreation.data["programId"] = - projectCreation.data.programInformation._id; + let tasksUpdated = await projectQueries.findOneAndUpdate({ + "_id": projectId, + "tasks._id": taskId + }, { + $set: { + "tasks.$.submissions": updateSubmission + } + }); - projectCreation.data["programExternalId"] = - projectCreation.data.programInformation.externalId; + return resolve(tasksUpdated); - projectCreation.data["solutionId"] = - projectCreation.data.solutionInformation._id; + } catch (error) { + return reject(error); + } + }) + } - projectCreation.data["solutionExternalId"] = - projectCreation.data.solutionInformation.externalId; + /** + * Solutions details + * @method + * @name solutionDetails + * @param {String} userToken - Logged in user token. + * @param {String} projectId - Project id. + * @param {Array} taskId - Tasks id. + * @returns {Object} + */ - projectCreation.data["userRole"] = bodyData.role; + static solutionDetails(userToken, projectId, taskId, bodyData = {}) { + return new Promise(async (resolve, reject) => { + try { + + let project = await projectQueries.projectDocument( + { + "_id": projectId, + "tasks._id": taskId + }, [ + "entityInformation._id", + "entityInformation.entityType", + "tasks.type", + "tasks._id", + "tasks.solutionDetails", + "tasks.submissions", + "tasks.observationInformation", + "tasks.externalId", + "programInformation._id", + "projectTemplateId" + ] + ); + if (!project.length > 0) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND + }; + } - projectCreation.data["appInformation"] = {}; + let currentTask = project[0].tasks.find(task => task._id == taskId); + + let solutionDetails = currentTask.solutionDetails; + + let assessmentOrObservationData = {}; + + if (project[0].entityInformation && project[0].entityInformation._id && project[0].programInformation && project[0].programInformation._id) { + + assessmentOrObservationData = { + entityId: project[0].entityInformation._id, + programId: project[0].programInformation._id + } + + if (currentTask.observationInformation) { + assessmentOrObservationData = currentTask.observationInformation; + } else { + + let assessmentOrObservation = { + token: userToken, + solutionDetails: solutionDetails, + entityId: assessmentOrObservationData.entityId, + programId: assessmentOrObservationData.programId, + project: { + "_id": projectId, + "taskId": taskId + } + + }; + + let assignedAssessmentOrObservation = + solutionDetails.type === CONSTANTS.common.ASSESSMENT ? + await _assessmentDetails(assessmentOrObservation) : + await _observationDetails(assessmentOrObservation, bodyData); + + if (!assignedAssessmentOrObservation.success) { + return resolve(assignedAssessmentOrObservation); + } + + assessmentOrObservationData = + _.merge(assessmentOrObservationData, assignedAssessmentOrObservation.data); + + if (!currentTask.solutionDetails.isReusable) { + assessmentOrObservationData["programId"] = + currentTask.solutionDetails.programId; + } + + await projectQueries.findOneAndUpdate({ + "_id": projectId, + "tasks._id": taskId + }, { + $set: { + "tasks.$.observationInformation": assessmentOrObservationData + } + }); + + } + + assessmentOrObservationData["entityType"] = project[0].entityInformation.entityType; - if (appName !== "") { - projectCreation.data["appInformation"]["appName"] = appName; - } + } + + if(currentTask.solutionDetails && !(_.isEmpty(currentTask.solutionDetails))) { - if (appVersion !== "") { - projectCreation.data["appInformation"]["appVersion"] = appVersion; - } + assessmentOrObservationData.solutionDetails = currentTask.solutionDetails; + } - if ( - solutionDetails.certificateTemplateId && - solutionDetails.certificateTemplateId !== "" - ) { - // <- Add certificate template details to projectCreation data if present -> - const certificateTemplateDetails = - await certificateTemplateQueries.certificateTemplateDocument({ - _id: solutionDetails.certificateTemplateId, + return resolve({ + success: true, + message: CONSTANTS.apiResponses.SOLUTION_DETAILS_FETCHED, + data: assessmentOrObservationData }); - // create certificate object and add data if certificate template is present. - if (certificateTemplateDetails.length > 0) { - projectCreation.data["certificate"] = _.pick( - certificateTemplateDetails[0], - ["templateUrl", "status", "criteria"] - ); - projectCreation.data["certificate"]["templateId"] = - solutionDetails.certificateTemplateId; - } + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); } + }) + } - let getUserProfileFromObservation = false; - - if (bodyData && Object.keys(bodyData).length > 0) { - if (bodyData.hasAcceptedTAndC) { - projectCreation.data.hasAcceptedTAndC = - bodyData.hasAcceptedTAndC; - } - if (bodyData.link) { - projectCreation.data.link = bodyData.link; - } - - if (bodyData.referenceFrom) { - projectCreation.data.referenceFrom = bodyData.referenceFrom; - - if (bodyData.submissions) { - if ( - bodyData.submissions.observationId && - bodyData.submissions.observationId != "" - ) { - getUserProfileFromObservation = true; - } - projectCreation.data.submissions = bodyData.submissions; - } - } - - if (bodyData.role) { - projectCreation.data["userRole"] = bodyData.role; - } - - if ( - solutionDetails.entityType && - bodyData[solutionDetails.entityType] - ) { - let entityInformation = - await surveyService.listEntitiesByLocationIds(userToken, [ - bodyData[solutionDetails.entityType], - ]); - - if (!entityInformation.success) { - throw { - message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } - - let entityDetails = await _entitiesMetaInformation( - entityInformation.data - ); + /** + * Creation of user targeted projects. + * @method + * @name detailsV2 + * @param {String} projectId - project id. + * @param {String} solutionId - solution id. + * @param {String} userId - logged in user id. + * @param {String} userToken - logged in user token. + * @param {Object} bodyData - Requested body data. + * @param {String} [appName = ""] - App name. + * @param {String} [appVersion = ""] - App version. + * @returns {Object} Project details. + */ - if (entityDetails && entityDetails.length > 0) { - projectCreation.data["entityInformation"] = entityDetails[0]; + static detailsV2( projectId,solutionId,userId,userToken,bodyData,appName = "",appVersion = "",templateId = "" ) { + return new Promise(async (resolve, reject) => { + try { + + let solutionExternalId = ""; + + if( templateId !== "" ) { + + let templateDocuments = + await projectTemplateQueries.templateDocument({ + "externalId" : templateId, + "isReusable" : false, + "solutionId" : { $exists : true } + },["solutionId","solutionExternalId"]); + + if( !templateDocuments.length > 0 ) { + throw { + message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } } - projectCreation.data.entityId = entityInformation.data[0]._id; - } + solutionId = templateDocuments[0].solutionId; + solutionExternalId = templateDocuments[0].solutionExternalId; } + + let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); + + if (projectId === "") { + // This will check wether the user user is targeted to solution or not based on his userRoleInformation + const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,userRoleInformation,solutionId) + //based on above api will check for projects wether its is private project or public project + const projectDetails = await projectQueries.projectDocument({ + solutionId: solutionId, + userId: userId, + isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true + }, ["_id"]); + if( projectDetails.length > 0 ) { + projectId = projectDetails[0]._id; + } else { + let isAPrivateSolution = (targetedSolutionId.data.isATargetedSolution === false) ? true : false; + let solutionDetails = {} + + if( templateId === "" ) { + // If solution Id of a private program is passed, fetch solution details + if ( isAPrivateSolution && solutionId != "" ) { + solutionDetails = await solutionsHelper.solutionDocuments({ + _id: solutionId, + isAPrivateProgram: true + }, + [ + "name", + "externalId", + "description", + "programId", + "programName", + "programDescription", + "programExternalId", + "isAPrivateProgram", + "projectTemplateId", + "entityType", + "entityTypeId", + "language", + "creator" + ]); + if( !solutionDetails.length > 0 ) { + throw { + status : HTTP_STATUS_CODE["bad_request"].status, + message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND + } + } + solutionDetails = solutionDetails[0]; + } else { + solutionDetails = + await coreService.solutionDetailsBasedOnRoleAndLocation( + userToken, + bodyData, + solutionId, + isAPrivateSolution + ); + + if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { + throw { + status : HTTP_STATUS_CODE["bad_request"].status, + message : CONSTANTS.apiResponses.SOLUTION_DOES_NOT_EXISTS_IN_SCOPE + } + } + + solutionDetails = solutionDetails.data; + } + + } else { + + solutionDetails = + await surveyService.listSolutions([solutionExternalId]); + if( !solutionDetails.success ) { + throw { + message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } + } + + solutionDetails = solutionDetails.data[0]; + + } + // check for requestForPIIConsent data + let queryData = {}; + queryData["_id"] = solutionDetails.programId; + let programDetails = await programsQueries.programsDocument(queryData,["requestForPIIConsent"]); + + // if requestForPIIConsent not there do not call program join + if ( programDetails.length > 0 && programDetails[0].hasOwnProperty('requestForPIIConsent')) { + + // program join API call it will increment the noOfResourcesStarted counter and will make user join program + // before creating any project this api has to called + let programUsers = await programUsersQueries.programUsersDocument( + { + userId : userId, + programId : solutionDetails.programId + }, + [ + "_id", + "resourcesStarted" + ] + ); + + if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { + let programJoinBody = {}; + programJoinBody.userRoleInformation = userRoleInformation; + programJoinBody.isResource = true; + programJoinBody.consentShared = true; + let joinProgramData = await coreService.joinProgram ( + solutionDetails.programId, + programJoinBody, + userToken + ); + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); + } + } + } + + let projectCreation = + await this.userAssignedProjectCreation( + solutionDetails.projectTemplateId, + userId, + userToken + ); - projectCreation.data.status = CONSTANTS.common.STARTED; - projectCreation.data.lastDownloadedAt = new Date(); - - // fetch userRoleInformation from observation if referenecFrom is observation - let addReportInfoToSolution = false; - if (getUserProfileFromObservation) { - let observationDetails = await surveyService.observationDetails( - userToken, - bodyData.submissions.observationId - ); - - if ( - observationDetails.data && - Object.keys(observationDetails.data).length > 0 && - observationDetails.data.userRoleInformation && - Object.keys(observationDetails.data.userRoleInformation) - .length > 0 - ) { - userRoleInformation = - observationDetails.data.userRoleInformation; - } - - if ( - observationDetails.data && - Object.keys(observationDetails.data).length > 0 && - observationDetails.data.userProfile && - Object.keys(observationDetails.data.userProfile).length > 0 - ) { - projectCreation.data.userProfile = - observationDetails.data.userProfile; - addReportInfoToSolution = true; - } else { - //Fetch user profile information by calling sunbird's user read api. - - let userProfile = await userProfileService.profile( - userToken, - userId - ); - if ( - userProfile.success && - userProfile.data && - userProfile.data.response - ) { - projectCreation.data.userProfile = userProfile.data.response; - addReportInfoToSolution = true; + if( !projectCreation.success ) { + return resolve(projectCreation); + } + + projectCreation.data["isAPrivateProgram"] = + solutionDetails.isAPrivateProgram; + + projectCreation.data.programInformation = { + _id : ObjectId(solutionDetails.programId), + externalId : solutionDetails.programExternalId, + description : + solutionDetails.programDescription ? solutionDetails.programDescription : "", + name : solutionDetails.programName + } + + projectCreation.data.solutionInformation = { + _id : ObjectId(solutionDetails._id), + externalId : solutionDetails.externalId, + description : + solutionDetails.description ? + solutionDetails.description : "", + name : solutionDetails.name + }; + + projectCreation.data["programId"] = + projectCreation.data.programInformation._id; + + projectCreation.data["programExternalId"] = + projectCreation.data.programInformation.externalId; + + projectCreation.data["solutionId"] = + projectCreation.data.solutionInformation._id; + + projectCreation.data["solutionExternalId"] = + projectCreation.data.solutionInformation.externalId; + + projectCreation.data["userRole"] = + bodyData.role; + + projectCreation.data["appInformation"] = {}; + + if( appName !== "" ) { + projectCreation.data["appInformation"]["appName"] = appName; + } + + if( appVersion !== "" ) { + projectCreation.data["appInformation"]["appVersion"] = appVersion; + } + + if ( solutionDetails.certificateTemplateId && solutionDetails.certificateTemplateId !== "" ) { + // <- Add certificate template details to projectCreation data if present -> + const certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : solutionDetails.certificateTemplateId + }); + + // create certificate object and add data if certificate template is present. + if ( certificateTemplateDetails.length > 0 ) { + projectCreation.data["certificate"] = _.pick(certificateTemplateDetails[0], ['templateUrl', 'status', 'criteria']); + projectCreation.data["certificate"]["templateId"] = solutionDetails.certificateTemplateId; + } + } + + let getUserProfileFromObservation = false; + + if( bodyData && Object.keys(bodyData).length > 0 ) { + + if( bodyData.hasAcceptedTAndC ) { + projectCreation.data.hasAcceptedTAndC = bodyData.hasAcceptedTAndC; + } + if( bodyData.link ) { + projectCreation.data.link = bodyData.link; + } + + if( bodyData.referenceFrom ) { + projectCreation.data.referenceFrom = bodyData.referenceFrom; + + if( bodyData.submissions ) { + if ( bodyData.submissions.observationId && bodyData.submissions.observationId != "" ) { + getUserProfileFromObservation = true; + } + projectCreation.data.submissions = bodyData.submissions; + } + } + + if( bodyData.role ) { + projectCreation.data["userRole"] = bodyData.role; + } + + if( + solutionDetails.entityType && bodyData[solutionDetails.entityType] + ) { + let entityInformation = + await surveyService.listEntitiesByLocationIds( + userToken, + [bodyData[solutionDetails.entityType]] + ); + + if( !entityInformation.success ) { + throw { + message : CONSTANTS.apiResponses.ENTITY_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } + } + + let entityDetails = await _entitiesMetaInformation( + entityInformation.data + ); + + if ( entityDetails && entityDetails.length > 0 ) { + projectCreation.data["entityInformation"] = entityDetails[0]; + } + + projectCreation.data.entityId = entityInformation.data[0]._id; + } + + } + + projectCreation.data.status = CONSTANTS.common.STARTED; + projectCreation.data.lastDownloadedAt = new Date(); + + // fetch userRoleInformation from observation if referenecFrom is observation + let addReportInfoToSolution = false; + if ( getUserProfileFromObservation ){ + + let observationDetails = await surveyService.observationDetails( + userToken, + bodyData.submissions.observationId + ); + + if( observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userRoleInformation && + Object.keys(observationDetails.data.userRoleInformation).length > 0 + ) { + + userRoleInformation = observationDetails.data.userRoleInformation; + + } + + if( observationDetails.data && + Object.keys(observationDetails.data).length > 0 && + observationDetails.data.userProfile && + Object.keys(observationDetails.data.userProfile).length > 0 + ) { + + projectCreation.data.userProfile = observationDetails.data.userProfile; + addReportInfoToSolution = true; + + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfile = await userProfileService.profile(userToken, userId); + if ( userProfile.success && + userProfile.data && + userProfile.data.response + ) { + projectCreation.data.userProfile = userProfile.data.response; + addReportInfoToSolution = true; + } + } + + } else { + //Fetch user profile information by calling sunbird's user read api. + + let userProfileData = await userProfileService.profile(userToken, userId); + if ( userProfileData.success && + userProfileData.data && + userProfileData.data.response + ) { + projectCreation.data.userProfile = userProfileData.data.response; + addReportInfoToSolution = true; + } + } + + projectCreation.data.userRoleInformation = userRoleInformation; + + //compare & update userProfile with userRoleInformation + if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { + let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( + projectCreation.data.userProfile, + userRoleInformation + ); + + if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { + projectCreation.data.userProfile = updatedUserProfile.data; + } + } + + let project = await projectQueries.createProject(projectCreation.data); + + if ( addReportInfoToSolution && project.solutionId ) { + let updateSolution = await solutionsHelper.addReportInformationInSolution( + project.solutionId, + project.userProfile + ); + } + + await kafkaProducersHelper.pushProjectToKafka(project); + + projectId = project._id; } - } - } else { - //Fetch user profile information by calling sunbird's user read api. - - let userProfileData = await userProfileService.profile( - userToken, - userId - ); - if ( - userProfileData.success && - userProfileData.data && - userProfileData.data.response - ) { - projectCreation.data.userProfile = - userProfileData.data.response; - addReportInfoToSolution = true; - } - } - - projectCreation.data.userRoleInformation = userRoleInformation; - - //compare & update userProfile with userRoleInformation - if ( - projectCreation.data.userProfile && - userRoleInformation && - Object.keys(userRoleInformation).length > 0 && - Object.keys(projectCreation.data.userProfile).length > 0 - ) { - let updatedUserProfile = - await _updateUserProfileBasedOnUserRoleInfo( - projectCreation.data.userProfile, - userRoleInformation - ); - - if ( - updatedUserProfile && - updatedUserProfile.success == true && - updatedUserProfile.profileMismatchFound == true - ) { - projectCreation.data.userProfile = updatedUserProfile.data; - } } - let project = await projectQueries.createProject( - projectCreation.data + let projectDetails = await this.details( + projectId, + userId, + userRoleInformation ); - - if (addReportInfoToSolution && project.solutionId) { - let updateSolution = - await solutionsHelper.addReportInformationInSolution( - project.solutionId, - project.userProfile - ); + + let revertStatusorNot = UTILS.revertStatusorNot(appVersion); + if ( revertStatusorNot ) { + projectDetails.data.status = UTILS.revertProjectStatus(projectDetails.data.status); + } else { + projectDetails.data.status = UTILS.convertProjectStatus(projectDetails.data.status); } + // make templateUrl downloadable befor passing to front-end + if ( projectDetails.data.certificate && + projectDetails.data.certificate.templateUrl && + projectDetails.data.certificate.templateUrl !== "" + ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [projectDetails.data.certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + projectDetails.data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; + } + } + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, + data: projectDetails.data + }); - await kafkaProducersHelper.pushProjectToKafka(project); - - projectId = project._id; - } - } - - let projectDetails = await this.details( - projectId, - userId, - userRoleInformation - ); - - let revertStatusorNot = UTILS.revertStatusorNot(appVersion); - if (revertStatusorNot) { - projectDetails.data.status = UTILS.revertProjectStatus( - projectDetails.data.status - ); - } else { - projectDetails.data.status = UTILS.convertProjectStatus( - projectDetails.data.status - ); - } - // make templateUrl downloadable befor passing to front-end - if ( - projectDetails.data.certificate && - projectDetails.data.certificate.templateUrl && - projectDetails.data.certificate.templateUrl !== "" - ) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl({ - filePaths: [projectDetails.data.certificate.templateUrl], + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: [] }); - if (certificateTemplateDownloadableUrl.success) { - projectDetails.data.certificate.templateUrl = - certificateTemplateDownloadableUrl.data[0].url; - } } + }) +} - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, - data: projectDetails.data, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: [], - }); - } - }); - } - - /** + /** * User assigned project creation data. * @method * @name userAssignedProjectCreation @@ -1789,747 +1663,730 @@ module.exports = class UserProjectsHelper { * @returns {String} - message. */ - static userAssignedProjectCreation(templateId, userId, userToken) { - return new Promise(async (resolve, reject) => { - try { - const projectTemplateData = - await projectTemplateQueries.templateDocument( - { - status: CONSTANTS.common.PUBLISHED, - _id: templateId, - isReusable: false, - }, - "all", - ["ratings", "noOfRatings", "averageRating"] - ); - - if (!projectTemplateData.length > 0) { - throw { - message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } + static userAssignedProjectCreation(templateId, userId, userToken) { + return new Promise(async (resolve, reject) => { + try { + const projectTemplateData = + await projectTemplateQueries.templateDocument({ + status: CONSTANTS.common.PUBLISHED, + _id: templateId, + isReusable: false + }, "all", + [ + "ratings", + "noOfRatings", + "averageRating" + ]); + + if (!projectTemplateData.length > 0) { + throw { + message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, + status: HTTP_STATUS_CODE['bad_request'].status + } + } - let result = { ...projectTemplateData[0] }; + let result = { ...projectTemplateData[0] }; - result.projectTemplateId = result._id; - result.projectTemplateExternalId = result.externalId; - result.userId = userId; - result.createdBy = userId; - result.updatedBy = userId; + result.projectTemplateId = result._id; + result.projectTemplateExternalId = result.externalId; + result.userId = userId; + result.createdBy = userId; + result.updatedBy = userId; - result.createdAt = new Date(); - result.updatedAt = new Date(); + result.createdAt = new Date(); + result.updatedAt = new Date(); - result.assesmentOrObservationTask = false; + result.assesmentOrObservationTask = false; - if ( - projectTemplateData[0].tasks && - projectTemplateData[0].tasks.length > 0 - ) { - const tasksAndSubTasks = - await projectTemplatesHelper.tasksAndSubTasks( - projectTemplateData[0]._id - ); + if (projectTemplateData[0].tasks && projectTemplateData[0].tasks.length > 0) { - if (tasksAndSubTasks.length > 0) { - result.tasks = _projectTask(tasksAndSubTasks); - result.tasks.forEach((task) => { - if ( - task.type === CONSTANTS.common.ASSESSMENT || - task.type === CONSTANTS.common.OBSERVATION - ) { - result.assesmentOrObservationTask = true; - } - }); + const tasksAndSubTasks = + await projectTemplatesHelper.tasksAndSubTasks( + projectTemplateData[0]._id + ); + + if (tasksAndSubTasks.length > 0) { - let taskReport = { - total: result.tasks.length, - }; + result.tasks = _projectTask(tasksAndSubTasks); + result.tasks.forEach(task => { + if ( + task.type === CONSTANTS.common.ASSESSMENT || + task.type === CONSTANTS.common.OBSERVATION + ) { + result.assesmentOrObservationTask = true; + } + }); - result.tasks.forEach((task) => { - if (task.isDeleted == false) { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - } else { - taskReport.total = taskReport.total - 1; - } - }); - result["taskReport"] = taskReport; - } - } + let taskReport = { + total: result.tasks.length + }; - delete result._id; + result.tasks.forEach(task => { + if ( task.isDeleted == false ) { - return resolve({ - success: true, - message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, - data: result, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, - }); - } - }); - } + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } - /** - * Add project. - * @method - * @name add - * @param {Object} data - body data. - * @param {String} userId - Logged in user id. - * @param {String} userToken - User token. - * @param {String} [appName = ""] - App Name. - * @param {String} [appVersion = ""] - App Version. - * @returns {Object} Project created information. - */ + } else { + taskReport.total = taskReport.total - 1; + } + + }); - static add(data, userId, userToken, appName = "", appVersion = "") { - return new Promise(async (resolve, reject) => { - try { - const projectsModel = Object.keys(schemas["projects"].schema); - let createProject = {}; - - createProject["userId"] = - createProject["createdBy"] = - createProject["updatedBy"] = - userId; - - //Fetch user profile information by calling sunbird's user read api. - - let userProfile = await userProfileService.profile(userToken, userId); - if ( - userProfile.success && - userProfile.data && - userProfile.data.response - ) { - createProject.userProfile = userProfile.data.response; - } + result["taskReport"] = taskReport; - let projectData = await _projectData(data); - if (projectData && projectData.success == true) { - createProject = _.merge(createProject, projectData.data); - } + } + } - let createNewProgramAndSolution = false; + delete result._id; - if (data.programId && data.programId !== "") { - createNewProgramAndSolution = false; - } else if (data.programName) { - createNewProgramAndSolution = true; - } + return resolve({ + success: true, + message: CONSTANTS.apiResponses.UPDATED_DOCUMENT_SUCCESSFULLY, + data: result + }); - if (data.entityId) { - let entityInformation = await _entitiesInformation([data.entityId]); + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); + } + }); + } - if (!entityInformation.success) { - return resolve(entityInformation); - } + /** + * Add project. + * @method + * @name add + * @param {Object} data - body data. + * @param {String} userId - Logged in user id. + * @param {String} userToken - User token. + * @param {String} [appName = ""] - App Name. + * @param {String} [appVersion = ""] - App Version. + * @returns {Object} Project created information. + */ + + static add(data, userId, userToken, appName = "", appVersion = "") { + return new Promise(async (resolve, reject) => { + try { + const projectsModel = Object.keys(schemas["projects"].schema); + let createProject = {}; + + createProject["userId"] = createProject["createdBy"] = createProject["updatedBy"] = userId; - createProject["entityInformation"] = entityInformation.data[0]; - createProject.entityId = entityInformation.data[0]._id; - } - if (createNewProgramAndSolution) { - let programAndSolutionInformation = - await this.createProgramAndSolution( - data.programId, - data.programName, - createProject.entityId ? [createProject.entityId] : "", - userToken - ); + //Fetch user profile information by calling sunbird's user read api. - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } - createProject = _.merge( - createProject, - programAndSolutionInformation.data - ); - } + let userProfile = await userProfileService.profile(userToken, userId); + if ( userProfile.success && + userProfile.data && + userProfile.data.response + ) { + createProject.userProfile = userProfile.data.response; + } - if (data.programId && data.programId !== "") { - let queryData = {}; - queryData["_id"] = data.programId; - let programDetails = await programsQueries.programsDocument( - queryData, - ["_id", "name", "description", "isAPrivateProgram"] - ); - if (!programDetails.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND, - }; - } - let programInformationData = {}; - programInformationData["programInformation"] = programDetails[0]; - createProject = _.merge(createProject, programInformationData); - } + - if (data.tasks) { - let taskReport = {}; + let projectData = await _projectData(data); + if (projectData && projectData.success == true) { + createProject = _.merge(createProject, projectData.data); + } - createProject.tasks = await _projectTask(data.tasks); + let createNewProgramAndSolution = false; - taskReport.total = createProject.tasks.length; + if (data.programId && data.programId !== "") { + createNewProgramAndSolution = false; + } + else if (data.programName) { + createNewProgramAndSolution = true; + } + + if (data.entityId) { + let entityInformation = + await _entitiesInformation([data.entityId]); - createProject.tasks.forEach((task) => { - if (task.isDeleted == false) { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - } else { - //if task is deleted it is not counted in total. - taskReport.total = taskReport.total - 1; - } - }); + if (!entityInformation.success) { + return resolve(entityInformation); + } - createProject["taskReport"] = taskReport; - } + createProject["entityInformation"] = entityInformation.data[0]; + createProject.entityId = entityInformation.data[0]._id; + } + if (createNewProgramAndSolution) { + + let programAndSolutionInformation = + await this.createProgramAndSolution( + data.programId, + data.programName, + createProject.entityId ? [createProject.entityId] : "", + userToken + ); + + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + createProject = + _.merge(createProject, programAndSolutionInformation.data); + } + + if (data.programId && data.programId !== "") { + + let queryData = {}; + queryData["_id"] = data.programId; + let programDetails = await programsQueries.programsDocument(queryData, + [ + "_id", + "name", + "description", + "isAPrivateProgram" + ] + ); + if( !programDetails.length > 0 ){ + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND + }; + } + let programInformationData = {}; + programInformationData["programInformation"] = programDetails[0]; + createProject = + _.merge(createProject, programInformationData); + } + - let booleanData = this.booleanData(schemas["projects"].schema); - let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); - - Object.keys(data).forEach((updateData) => { - if ( - !createProject[updateData] && - projectsModel.includes(updateData) - ) { - if (booleanData.includes(updateData)) { - createProject[updateData] = UTILS.convertStringToBoolean( - data[updateData] - ); - } else if (mongooseIdData.includes(updateData)) { - createProject[updateData] = ObjectId(data[updateData]); - } else { - createProject[updateData] = data[updateData]; - } - } - }); + if (data.tasks) { - createProject["appInformation"] = {}; - if (appName !== "") { - createProject["appInformation"]["appName"] = appName; - } + let taskReport = {}; - if (appVersion !== "") { - createProject["appInformation"]["appVersion"] = appVersion; - } + createProject.tasks = await _projectTask( + data.tasks + ); - createProject["lastDownloadedAt"] = new Date(); + taskReport.total = createProject.tasks.length; + + createProject.tasks.forEach(task => { + if ( task.isDeleted == false ) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + } else { + //if task is deleted it is not counted in total. + taskReport.total = taskReport.total - 1; + } + + }); + + createProject["taskReport"] = taskReport; + } - if (data.profileInformation) { - createProject.userRoleInformation = data.profileInformation; - } + let booleanData = this.booleanData(schemas["projects"].schema); + let mongooseIdData = this.mongooseIdData(schemas["projects"].schema); - createProject.status = UTILS.convertProjectStatus(data.status); - let userProject = await projectQueries.createProject(createProject); - await kafkaProducersHelper.pushProjectToKafka(userProject); + Object.keys(data).forEach(updateData => { + if ( + !createProject[updateData] && + projectsModel.includes(updateData) + ) { - if (!userProject._id) { - throw { - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_CREATED, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } + if (booleanData.includes(updateData)) { - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_CREATED, - data: { - programId: - userProject.programInformation && - userProject.programInformation._id - ? userProject.programInformation._id - : data.programId, - projectId: userProject._id, - lastDownloadedAt: userProject.lastDownloadedAt, - hasAcceptedTAndC: userProject.hasAcceptedTAndC - ? userProject.hasAcceptedTAndC - : false, - }, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, - }); - } - }); - } + createProject[updateData] = + UTILS.convertStringToBoolean(data[updateData]); - /** - * share project and task pdf report. - * @method - * @name share - * @param {String} [projectId] - projectId. - * @returns {Object} Downloadable pdf url. - */ + } else if (mongooseIdData.includes(updateData)) { + createProject[updateData] = ObjectId(data[updateData]); + } else { + createProject[updateData] = data[updateData]; + } + } + }); - static share(projectId = "", taskIds = [], userToken, appVersion) { - return new Promise(async (resolve, reject) => { - try { - let projectPdf = true; - let projectDocument = []; - - let query = { - _id: projectId, - isDeleted: false, - }; - - if (!taskIds.length) { - projectDocument = await projectQueries.projectDocument(query, [ - "title", - "status", - "metaInformation.goal", - "metaInformation.duration", - "startDate", - "description", - "endDate", - "tasks", - "categories", - "programInformation.name", - "recommendedFor", - "link", - "remarks", - "attachments", - "taskReport.completed", - ]); - } else { - projectPdf = false; - - let aggregateData = [ - { $match: { _id: ObjectId(projectId), isDeleted: false } }, - { - $project: { - status: 1, - title: 1, - startDate: 1, - "metaInformation.goal": 1, - "metaInformation.duration": 1, - categories: 1, - "programInformation.name": 1, - description: 1, - recommendedFor: 1, - link: 1, - remarks: 1, - attachments: 1, - "taskReport.completed": 1, - tasks: { - $filter: { - input: "$tasks", - as: "tasks", - cond: { $in: ["$$tasks._id", taskIds] }, - }, - }, - }, - }, - ]; + createProject["appInformation"] = {}; + if (appName !== "") { + createProject["appInformation"]["appName"] = appName; + } - projectDocument = await projectQueries.getAggregate(aggregateData); - } + if (appVersion !== "") { + createProject["appInformation"]["appVersion"] = appVersion; + } - if (!projectDocument.length) { - throw { - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } + createProject["lastDownloadedAt"] = new Date(); - projectDocument = projectDocument[0]; - projectDocument.goal = projectDocument.metaInformation - ? projectDocument.metaInformation.goal - : ""; - projectDocument.duration = projectDocument.metaInformation - ? projectDocument.metaInformation.duration - : ""; - projectDocument.programName = projectDocument.programInformation - ? projectDocument.programInformation.name - : ""; - projectDocument.remarks = projectDocument.remarks - ? projectDocument.remarks - : ""; - projectDocument.taskcompleted = projectDocument.taskReport.completed - ? projectDocument.taskReport.completed - : CONSTANTS.common.DEFAULT_TASK_COMPLETED; - - //store tasks and attachment data into object - let projectFilter = { - tasks: projectDocument.tasks, - attachments: projectDocument.attachments, - }; - - //returns project tasks and attachments with downloadable urls - let projectDataWithUrl = await _projectInformation(projectFilter); - - //replace projectDocument Data - if ( - projectDataWithUrl.success && - projectDataWithUrl.data && - projectDataWithUrl.data.tasks && - projectDataWithUrl.data.tasks.length > 0 - ) { - projectDocument.tasks = projectDataWithUrl.data.tasks; - } + if (data.profileInformation) { + createProject.userRoleInformation = data.profileInformation; + } - if ( - projectDataWithUrl.success && - projectDataWithUrl.data && - projectDataWithUrl.data.attachments && - projectDataWithUrl.data.attachments.length > 0 - ) { - projectDocument.attachments = projectDataWithUrl.data.attachments; - } + createProject.status = UTILS.convertProjectStatus(data.status); + let userProject = await projectQueries.createProject( + createProject + ); + + await kafkaProducersHelper.pushProjectToKafka(userProject); + + if (!userProject._id) { + throw { + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_CREATED, + status: HTTP_STATUS_CODE['bad_request'].status + } + } - //get image link and other document links - let imageLink = []; - let evidenceLink = []; - if ( - projectDocument.attachments && - projectDocument.attachments.length > 0 - ) { - projectDocument.attachments.forEach((attachment) => { - if ( - attachment.type == CONSTANTS.common.IMAGE_DATA_TYPE && - attachment.url && - attachment.url !== "" - ) { - imageLink.push(attachment.url); - } else if ( - attachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK && - attachment.name && - attachment.name !== "" - ) { - let data = { - type: attachment.type, - url: attachment.name, - }; - evidenceLink.push(data); - } else if (attachment.url && attachment.url !== "") { - let data = { - type: attachment.type, - url: attachment.url, - }; - evidenceLink.push(data); + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_CREATED, + data: { + programId: + userProject.programInformation && userProject.programInformation._id ? + userProject.programInformation._id : data.programId, + projectId: userProject._id, + lastDownloadedAt: userProject.lastDownloadedAt, + hasAcceptedTAndC : userProject.hasAcceptedTAndC ? userProject.hasAcceptedTAndC : false + } + }); + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); } - }); - } - projectDocument.evidenceLink = evidenceLink; - projectDocument.imageLink = imageLink; - - projectDocument.category = []; - - if ( - projectDocument.categories && - projectDocument.categories.length > 0 - ) { - projectDocument.categories.forEach((category) => { - projectDocument.category.push(category.name); - }); - } + }) + } - projectDocument.recommendedForRoles = []; - if ( - projectDocument.recommendedFor && - projectDocument.recommendedFor.length > 0 - ) { - projectDocument.recommendedFor.forEach((recommend) => { - projectDocument.recommendedForRoles.push(recommend.code); - }); - } + /** + * share project and task pdf report. + * @method + * @name share + * @param {String} [projectId] - projectId. + * @returns {Object} Downloadable pdf url. + */ - let tasks = []; - if (projectDocument.tasks.length > 0) { - projectDocument.tasks.forEach((task) => { - let subtasks = []; - if (!task.isDeleted) { - if (task.children.length > 0) { - task.children.forEach((children) => { - if (!children.isDeleted) { - subtasks.push(children); - } - }); - } - task.children = subtasks; - tasks.push(task); - } - }); - projectDocument.tasks = tasks; - } + static share(projectId = "", taskIds = [], userToken,appVersion) { + return new Promise(async (resolve, reject) => { + try { - delete projectDocument.categories; - delete projectDocument.metaInformation; - delete projectDocument.programInformation; - delete projectDocument.recommendedFor; + let projectPdf = true; + let projectDocument = []; - if (UTILS.revertStatusorNot(appVersion)) { - projectDocument.status = UTILS.revertProjectStatus( - projectDocument.status - ); - } - let response = await reportService.projectAndTaskReport( - userToken, - projectDocument, - projectPdf - ); - - if (response && response.success == true) { - return resolve({ - success: true, - message: CONSTANTS.apiResponses.REPORT_GENERATED_SUCCESSFULLY, - data: { - data: { - downloadUrl: response.data.pdfUrl, - }, - }, - }); - } else { - throw { - message: CONSTANTS.apiResponses.COULD_NOT_GENERATE_PDF_REPORT, - }; - } - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: {}, - }); - } - }); - } + let query = { + _id: projectId, + isDeleted: false + } - /** - * Get list of user projects with the targetted ones. - * @method - * @name userAssigned - * @param {String} userId - Logged in user id. - * @param {Number} pageSize - Page size. - * @param {Number} pageNo - Page No. - * @param {String} search - Search text. - * @param {String} filter - filter text. - * @returns {Object} + if (!taskIds.length ) { + + projectDocument = await projectQueries.projectDocument + ( + query, + [ + "title", + "status", + "metaInformation.goal", + "metaInformation.duration", + "startDate", + "description", + "endDate", + "tasks", + "categories", + "programInformation.name", + "recommendedFor", + "link", + "remarks", + "attachments", + "taskReport.completed" + ] + ); + } + else { + projectPdf = false; + + let aggregateData = [ + { "$match": { _id: ObjectId(projectId), isDeleted: false} }, + { "$project": { + "status": 1, "title": 1, "startDate": 1, "metaInformation.goal": 1, "metaInformation.duration":1, + "categories" : 1, "programInformation.name": 1, "description" : 1, "recommendedFor" : 1, "link" : 1, "remarks" : 1, "attachments" : 1, "taskReport.completed" : 1, + tasks: { "$filter": { + input: '$tasks', + as: 'tasks', + cond: { "$in": ['$$tasks._id', taskIds]} + }} + }}] + + projectDocument = await projectQueries.getAggregate(aggregateData); + } + + if (!projectDocument.length) { + throw { + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, + status: HTTP_STATUS_CODE['bad_request'].status + } + } + + projectDocument = projectDocument[0]; + projectDocument.goal = projectDocument.metaInformation ? projectDocument.metaInformation.goal : ""; + projectDocument.duration = projectDocument.metaInformation ? projectDocument.metaInformation.duration : ""; + projectDocument.programName = projectDocument.programInformation ? projectDocument.programInformation.name : ""; + projectDocument.remarks = projectDocument.remarks ? projectDocument.remarks : ""; + projectDocument.taskcompleted = projectDocument.taskReport.completed ? projectDocument.taskReport.completed : CONSTANTS.common.DEFAULT_TASK_COMPLETED; + + //store tasks and attachment data into object + let projectFilter = { + tasks : projectDocument.tasks, + attachments : projectDocument.attachments + } + + //returns project tasks and attachments with downloadable urls + let projectDataWithUrl = await _projectInformation( projectFilter ); + + //replace projectDocument Data + if ( projectDataWithUrl.success && + projectDataWithUrl.data && + projectDataWithUrl.data.tasks && + projectDataWithUrl.data.tasks.length > 0 + ) { + + projectDocument.tasks = projectDataWithUrl.data.tasks ; + } + + if ( projectDataWithUrl.success && + projectDataWithUrl.data && + projectDataWithUrl.data.attachments && + projectDataWithUrl.data.attachments.length > 0 + ) { + projectDocument.attachments = projectDataWithUrl.data.attachments ; + } + + + //get image link and other document links + let imageLink = []; + let evidenceLink = []; + if ( projectDocument.attachments && projectDocument.attachments.length > 0 ) { + projectDocument.attachments.forEach( attachment => { + if( attachment.type == CONSTANTS.common.IMAGE_DATA_TYPE && attachment.url && attachment.url !== "" ) { + imageLink.push( attachment.url ); + } else if ( attachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK && attachment.name && attachment.name !== "" ) { + let data = { + type : attachment.type, + url : attachment.name + } + evidenceLink.push( data ); + } else if ( attachment.url && attachment.url !== "" ) { + let data = { + type : attachment.type, + url : attachment.url + } + evidenceLink.push( data ); + } + }) + } + projectDocument.evidenceLink = evidenceLink; + projectDocument.imageLink = imageLink; + + projectDocument.category = []; + + if (projectDocument.categories && projectDocument.categories.length > 0) { + projectDocument.categories.forEach( category => { + projectDocument.category.push(category.name); + }) + } + + projectDocument.recommendedForRoles = []; + + if (projectDocument.recommendedFor && projectDocument.recommendedFor.length > 0) { + projectDocument.recommendedFor.forEach( recommend => { + projectDocument.recommendedForRoles.push(recommend.code); + }) + } + + let tasks = []; + if (projectDocument.tasks.length > 0) { + projectDocument.tasks.forEach( task => { + let subtasks = []; + if (!task.isDeleted) { + if (task.children.length > 0) { + task.children.forEach(children => { + if (!children.isDeleted) { + subtasks.push(children); + } + }) + } + task.children = subtasks; + tasks.push(task); + } + }) + projectDocument.tasks = tasks; + } + + delete projectDocument.categories; + delete projectDocument.metaInformation; + delete projectDocument.programInformation; + delete projectDocument.recommendedFor; + + if (UTILS.revertStatusorNot(appVersion)) { + projectDocument.status = UTILS.revertProjectStatus(projectDocument.status); + } + let response = await reportService.projectAndTaskReport(userToken, projectDocument, projectPdf); + + if (response && response.success == true) { + return resolve({ + success: true, + message: CONSTANTS.apiResponses.REPORT_GENERATED_SUCCESSFULLY, + data: { + data: { + downloadUrl: response.data.pdfUrl + } + } + }); + } + + else { + throw { + message: CONSTANTS.apiResponses.COULD_NOT_GENERATE_PDF_REPORT, + } + } + + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: {} + }); + } + }) + } + + /** + * Get list of user projects with the targetted ones. + * @method + * @name userAssigned + * @param {String} userId - Logged in user id. + * @param {Number} pageSize - Page size. + * @param {Number} pageNo - Page No. + * @param {String} search - Search text. + * @param {String} filter - filter text. + * @returns {Object} */ - static userAssigned(userId, pageSize, pageNo, search, filter) { + static userAssigned( userId,pageSize,pageNo,search, filter ) { return new Promise(async (resolve, reject) => { - try { - let query = { - userId: userId, - isDeleted: false, - }; - - let searchQuery = []; - - if (search !== "") { - searchQuery = [ - { title: new RegExp(search, "i") }, - { description: new RegExp(search, "i") }, - ]; - } + try { - if (filter && filter !== "") { - if (filter === CONSTANTS.common.CREATED_BY_ME) { - query["referenceFrom"] = { - $ne: CONSTANTS.common.LINK, - }; - query["isAPrivateProgram"] = { - $ne: false, - }; - } else if (filter == CONSTANTS.common.ASSIGN_TO_ME) { - query["isAPrivateProgram"] = false; - } else { - query["referenceFrom"] = CONSTANTS.common.LINK; - } - } + let query = { + userId : userId, + isDeleted : false + } - let projects = await this.projects( - query, - pageSize, - pageNo, - searchQuery, - [ - "title", - "description", - "solutionId", - "programId", - "programInformation.name", - "projectTemplateId", - "solutionExternalId", - "lastDownloadedAt", - "hasAcceptedTAndC", - "referenceFrom", - "status", - "certificate", - ] - ); - - let totalCount = 0; - let data = []; - if ( - projects.success && - projects.data && - projects.data.data && - Object.keys(projects.data.data).length > 0 - ) { - totalCount = projects.data.count; - data = projects.data.data; - - if (data.length > 0) { - let templateFilePath = []; - data.forEach((projectData) => { - projectData.name = projectData.title; - - if (projectData.programInformation) { - projectData.programName = projectData.programInformation.name; - delete projectData.programInformation; - } - - if (projectData.solutionExternalId) { - projectData.externalId = projectData.solutionExternalId; - delete projectData.solutionExternalId; - } - - projectData.type = CONSTANTS.common.IMPROVEMENT_PROJECT; - delete projectData.title; - - if ( - projectData.certificate && - projectData.certificate.osid && - projectData.certificate.osid !== "" && - projectData.certificate.templateUrl && - projectData.certificate.templateUrl !== "" - ) { - templateFilePath.push(projectData.certificate.templateUrl); - } - }); + let searchQuery = []; - if (templateFilePath.length > 0) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl({ - filePaths: templateFilePath, - }); - if (!certificateTemplateDownloadableUrl.success) { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND, - }; - } - // map downloadable templateUrl to corresponding project data - data.forEach((projectData) => { - if (projectData.certificate) { - var itemFromUrlArray = - certificateTemplateDownloadableUrl.data.find( - (item) => - item.filePath == projectData.certificate.templateUrl - ); - if (itemFromUrlArray) { - projectData.certificate.templateUrl = itemFromUrlArray.url; - } + if (search !== "") { + searchQuery = [ + { "title" : new RegExp(search, 'i') }, + { "description" : new RegExp(search, 'i') } + ]; + } + + if ( filter && filter !== "" ) { + if( filter === CONSTANTS.common.CREATED_BY_ME ) { + query["referenceFrom"] = { + $ne : CONSTANTS.common.LINK + }; + query["isAPrivateProgram"] = { + $ne : false + }; + } else if( filter == CONSTANTS.common.ASSIGN_TO_ME ) { + query["isAPrivateProgram"] = false; + } else{ + query["referenceFrom"] = CONSTANTS.common.LINK; } - }); } - } - } + + let projects = await this.projects( + query, + pageSize, + pageNo, + searchQuery, + [ + "title", + "description", + "solutionId", + "programId", + "programInformation.name", + "projectTemplateId", + "solutionExternalId", + "lastDownloadedAt", + "hasAcceptedTAndC", + "referenceFrom", + "status", + "certificate" + ] + ); + + let totalCount = 0; + let data = []; + if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { + + totalCount = projects.data.count; + data = projects.data.data; + + if( data.length > 0 ) { + let templateFilePath = []; + data.forEach( projectData => { + + projectData.name = projectData.title; + + + if (projectData.programInformation) { + projectData.programName = projectData.programInformation.name; + delete projectData.programInformation; + } + + if (projectData.solutionExternalId) { + projectData.externalId = projectData.solutionExternalId; + delete projectData.solutionExternalId; + } + + projectData.type = CONSTANTS.common.IMPROVEMENT_PROJECT; + delete projectData.title; + + if (projectData.certificate && + projectData.certificate.osid && + projectData.certificate.osid !== "" && + projectData.certificate.templateUrl && + projectData.certificate.templateUrl !== "" + ) { + templateFilePath.push(projectData.certificate.templateUrl); + } + + }); + + if( templateFilePath.length > 0 ) { + + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: templateFilePath + } + ); + if ( !certificateTemplateDownloadableUrl.success ) { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; + } + // map downloadable templateUrl to corresponding project data + data.forEach(projectData => { + if (projectData.certificate) { + var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find(item=> item.filePath == projectData.certificate.templateUrl); + if (itemFromUrlArray) { + projectData.certificate.templateUrl = itemFromUrlArray.url; + } + } + } + + ) + } - return resolve({ - success: true, - message: CONSTANTS.apiResponses.USER_ASSIGNED_PROJECT_FETCHED, - data: { - data: data, - count: totalCount, - }, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - data: { - description: CONSTANTS.common.PROJECT_DESCRIPTION, - data: [], - count: 0, - }, - }); - } - }); + } + } + + return resolve({ + success : true, + message : CONSTANTS.apiResponses.USER_ASSIGNED_PROJECT_FETCHED, + data : { + data: data, + count: totalCount + } + }); + + } catch (error) { + return resolve({ + success : false, + message : error.message, + status : + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + data : { + description : CONSTANTS.common.PROJECT_DESCRIPTION, + data : [], + count : 0 + } + }); + } + }) } /** - * List of user imported projects. - * @method - * @name importedProjects - * @param {String} userId - Logged in user id. - * @param {String} programId - program id. - * @returns {Object} + * List of user imported projects. + * @method + * @name importedProjects + * @param {String} userId - Logged in user id. + * @param {String} programId - program id. + * @returns {Object} */ - static importedProjects(userId, programId) { + static importedProjects( userId,programId ) { return new Promise(async (resolve, reject) => { - try { - let filterQuery = { - userId: userId, - // referenceFrom : { $exists : true,$eq : CONSTANTS.common.OBSERVATION_REFERENCE_KEY }, - Commented as this filter is not useful. - 4.7 Sprint - 25Feb2022 - isDeleted: false, - }; - - if (programId !== "") { - filterQuery["programId"] = programId; - } + try { - let importedProjects = await projectQueries.projectDocument( - filterQuery, - [ - "solutionInformation", - "programInformation", - "title", - "description", - "projectTemplateId", - "certificate.templateId", - ] - ); + let filterQuery = { + userId : userId, + // referenceFrom : { $exists : true,$eq : CONSTANTS.common.OBSERVATION_REFERENCE_KEY }, - Commented as this filter is not useful. - 4.7 Sprint - 25Feb2022 + isDeleted: false + }; - return resolve({ - success: true, - message: CONSTANTS.apiResponses.IMPORTED_PROJECTS_FETCHED, - data: importedProjects, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - data: { - description: CONSTANTS.common.PROJECT_DESCRIPTION, - data: [], - count: 0, - }, - }); - } - }); + if( programId !== "" ) { + filterQuery["programId"] = programId; + } + + let importedProjects = await projectQueries.projectDocument( + filterQuery, + [ + "solutionInformation", + "programInformation", + "title", + "description", + "projectTemplateId", + "certificate.templateId" + ] + ); + + return resolve({ + success : true, + message : CONSTANTS.apiResponses.IMPORTED_PROJECTS_FETCHED, + data : importedProjects + }); + + } catch (error) { + return resolve({ + success : false, + message : error.message, + status : + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + data : { + description : CONSTANTS.common.PROJECT_DESCRIPTION, + data : [], + count : 0 + } + }); + } + }) } /** @@ -2538,1965 +2395,1772 @@ module.exports = class UserProjectsHelper { * @name list * @returns {Array} List of projects. */ - - static list(bodyData) { + + static list( bodyData ) { return new Promise(async (resolve, reject) => { - try { - let projects = await projectQueries.projectDocument( - bodyData.query, - bodyData.projection, - bodyData.skipFields - ); + try { + let projects = await projectQueries.projectDocument( + bodyData.query, + bodyData.projection, + bodyData.skipFields + ); - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - result: projects, - }); - } catch (error) { - return reject(error); - } + return resolve({ + success : true, + message : CONSTANTS.apiResponses.PROJECTS_FETCHED, + result : projects + }); + + } catch (error) { + return reject(error); + } }); } /** - * Create project from template. - * @method - * @name importFromLibrary - * @param {String} projectTemplateId - project template id. - * @param {Object} requestedData - body data. - * @param {String} userId - Logged in user id. - * @param {String} userToken - User token. - * @param {Boolean} isATargetedSolution - User targeted or not . - * @returns {Object} Project created information. - */ + * Create project from template. + * @method + * @name importFromLibrary + * @param {String} projectTemplateId - project template id. + * @param {Object} requestedData - body data. + * @param {String} userId - Logged in user id. + * @param {String} userToken - User token. + * @param {Boolean} isATargetedSolution - User targeted or not . + * @returns {Object} Project created information. + */ + + static importFromLibrary(projectTemplateId, requestedData, userToken, userId, isATargetedSolution = "" ) { + return new Promise(async (resolve, reject) => { + try { + + isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); + + let libraryProjects = + await libraryCategoriesHelper.projectDetails( + projectTemplateId, + "", + isATargetedSolution + ); + + if ( + libraryProjects.data && + !Object.keys(libraryProjects.data).length > 0 + ) { + throw { + message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, + status: HTTP_STATUS_CODE['bad_request'].status + }; + + } + + let taskReport = {}; - static importFromLibrary( - projectTemplateId, - requestedData, - userToken, - userId, - isATargetedSolution = "" - ) { - return new Promise(async (resolve, reject) => { - try { - isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); - - let libraryProjects = await libraryCategoriesHelper.projectDetails( - projectTemplateId, - "", - isATargetedSolution - ); - - if ( - libraryProjects.data && - !Object.keys(libraryProjects.data).length > 0 - ) { - throw { - message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } + if ( + libraryProjects.data.tasks && + libraryProjects.data.tasks.length > 0 + ) { - let taskReport = {}; - - if ( - libraryProjects.data.tasks && - libraryProjects.data.tasks.length > 0 - ) { - libraryProjects.data.tasks = await _projectTask( - libraryProjects.data.tasks, - isATargetedSolution === false ? false : true - ); - - taskReport.total = libraryProjects.data.tasks.length; - - libraryProjects.data.tasks.forEach((task) => { - if (task.isDeleted == false) { - if (!taskReport[task.status]) { - taskReport[task.status] = 1; - } else { - taskReport[task.status] += 1; - } - } else { - //reduce total count if task is deleted. - taskReport.total = taskReport.total - 1; + libraryProjects.data.tasks = await _projectTask( + libraryProjects.data.tasks, + isATargetedSolution === false ? false : true + ); + + taskReport.total = libraryProjects.data.tasks.length; + + libraryProjects.data.tasks.forEach(task => { + if ( task.isDeleted == false ) { + if (!taskReport[task.status]) { + taskReport[task.status] = 1; + } else { + taskReport[task.status] += 1; + } + } else { + //reduce total count if task is deleted. + taskReport.total = taskReport.total - 1; + } + + }); + + libraryProjects.data["taskReport"] = taskReport; + } + + if (requestedData.entityId && requestedData.entityId !== "") { + + let entityInformation = + await _entitiesInformation([requestedData.entityId]); + + if (!entityInformation.success) { + return resolve(entityInformation); + } + + libraryProjects.data["entityInformation"] = entityInformation.data[0]; + libraryProjects.data.entityId = entityInformation.data[0]._id; + } + + if( requestedData.solutionId && requestedData.solutionId !== "" && isATargetedSolution === false ){ + let programAndSolutionInformation = {}; + // Check if solutionId passed is private or not, if private and data is present, create program and solution information. + let solutionDetails = await solutionsHelper.solutionDocuments({ + _id: requestedData.solutionId, + isAPrivateProgram: true + }, + [ + "_id", + "name", + "externalId", + "description", + "programId", + "programName", + "programDescription", + "programExternalId", + "isAPrivateProgram", + "projectTemplateId", + "entityType", + "certificateTemplateId", + "parentSolutionId" + ]); + // private solution exists + if ( solutionDetails.length > 0 && solutionDetails[0].parentSolutionId ) { + // This function will return programAndSolutionInformation + /** + * function privateProgramAndSolutionDetails + * Request: + * @param {solutionDetails} solution data + * @response Program and solution details + */ + programAndSolutionInformation = await this.getProgramAndSolutionDetails(solutionDetails[0]); + } else { + programAndSolutionInformation = + await this.createProgramAndSolution( + requestedData.programId, + requestedData.programName, + requestedData.entityId ? [requestedData.entityId] : "", + userToken, + requestedData.solutionId, + isATargetedSolution + ); + } + + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + + libraryProjects.data = _.merge( + libraryProjects.data, + programAndSolutionInformation.data + ) + + libraryProjects.data["referenceFrom"] = CONSTANTS.common.LINK; + } + else if ( + (requestedData.programId && requestedData.programId !== "") || + (requestedData.programName && requestedData.programName !== "" ) + ) { + + let programAndSolutionInformation = + await this.createProgramAndSolution( + requestedData.programId, + requestedData.programName, + requestedData.entityId ? [requestedData.entityId] : "", + userToken + ); + + if (!programAndSolutionInformation.success) { + return resolve(programAndSolutionInformation); + } + + if ( + libraryProjects.data["entityInformation"] && + libraryProjects.data["entityInformation"].entityType !== + programAndSolutionInformation.data.solutionInformation.entityType + ) { + throw { + message: CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, + status: HTTP_STATUS_CODE['bad_request'].status + } + } + + libraryProjects.data = _.merge( + libraryProjects.data, + programAndSolutionInformation.data + ) + } + // <- Add certificate template data + if ( + libraryProjects.data.certificateTemplateId && + libraryProjects.data.certificateTemplateId !== "" + ){ + // <- Add certificate template details to projectCreation data if present -> + const certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : libraryProjects.data.certificateTemplateId + }); + + // create certificate object and add data if certificate template is present. + if ( certificateTemplateDetails.length > 0 ) { + libraryProjects.data["certificate"] = _.pick(certificateTemplateDetails[0], ['templateUrl', 'status', 'criteria']); + } + libraryProjects.data["certificate"]["templateId"] = libraryProjects.data.certificateTemplateId; + delete libraryProjects.data.certificateTemplateId; + } + + //Fetch user profile information by calling sunbird's user read api. + let addReportInfoToSolution = false; + let userProfile = await userProfileService.profile(userToken, userId); + if ( userProfile.success && + userProfile.data && + userProfile.data.response + ) { + libraryProjects.data.userProfile = userProfile.data.response; + addReportInfoToSolution = true; + } + + libraryProjects.data.userId = libraryProjects.data.updatedBy = libraryProjects.data.createdBy = userId; + libraryProjects.data.lastDownloadedAt = new Date(); + libraryProjects.data.status = CONSTANTS.common.STARTED; + + if (requestedData.startDate) { + libraryProjects.data.startDate = requestedData.startDate; + } + + if (requestedData.endDate) { + libraryProjects.data.endDate = requestedData.endDate; + } + + if (requestedData.hasAcceptedTAndC) { + libraryProjects.data.hasAcceptedTAndC = true; + } + + libraryProjects.data.projectTemplateId = libraryProjects.data._id; + libraryProjects.data.projectTemplateExternalId = libraryProjects.data.externalId; + + let projectCreation = await database.models.projects.create( + _.omit(libraryProjects.data, ["_id"]) + ); + + if ( addReportInfoToSolution && projectCreation._doc.solutionId ) { + + let updateSolution = await solutionsHelper.addReportInformationInSolution( + projectCreation._doc.solutionId, + projectCreation._doc.userProfile + ); + } + + await kafkaProducersHelper.pushProjectToKafka(projectCreation); + + if (requestedData.rating && requestedData.rating > 0) { + await projectTemplatesHelper.ratings( + projectTemplateId, + requestedData.rating, + userToken + ); + } + + projectCreation = await _projectInformation(projectCreation._doc); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data: projectCreation.data + }); + + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); } - }); + }) + } - libraryProjects.data["taskReport"] = taskReport; - } + /** + * get project details. + * @method + * @name userProject + * @param {String} projectId - project id. + * @returns {Object} Project details. + */ - if (requestedData.entityId && requestedData.entityId !== "") { - let entityInformation = await _entitiesInformation([ - requestedData.entityId, - ]); + static userProject(projectId) { + return new Promise(async (resolve, reject) => { + try { - if (!entityInformation.success) { - return resolve(entityInformation); - } + const projectDetails = await projectQueries.projectDocument({ + _id: projectId, + }, "all"); - libraryProjects.data["entityInformation"] = entityInformation.data[0]; - libraryProjects.data.entityId = entityInformation.data[0]._id; - } + if (!projectDetails.length > 0) { - if ( - requestedData.solutionId && - requestedData.solutionId !== "" && - isATargetedSolution === false - ) { - let programAndSolutionInformation = {}; - // Check if solutionId passed is private or not, if private and data is present, create program and solution information. - let solutionDetails = await solutionsHelper.solutionDocuments( - { - _id: requestedData.solutionId, - isAPrivateProgram: true, - }, - [ - "_id", - "name", - "externalId", - "description", - "programId", - "programName", - "programDescription", - "programExternalId", - "isAPrivateProgram", - "projectTemplateId", - "entityType", - "certificateTemplateId", - "parentSolutionId", - ] - ); - // private solution exists - if ( - solutionDetails.length > 0 && - solutionDetails[0].parentSolutionId - ) { - // This function will return programAndSolutionInformation - /** - * function privateProgramAndSolutionDetails - * Request: - * @param {solutionDetails} solution data - * @response Program and solution details - */ - programAndSolutionInformation = - await this.getProgramAndSolutionDetails(solutionDetails[0]); - } else { - programAndSolutionInformation = await this.createProgramAndSolution( - requestedData.programId, - requestedData.programName, - requestedData.entityId ? [requestedData.entityId] : "", - userToken, - requestedData.solutionId, - isATargetedSolution - ); - } + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND + } + } + + return resolve( { + success: true, + message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, + data: projectDetails[0] + }); - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } - libraryProjects.data = _.merge( - libraryProjects.data, - programAndSolutionInformation.data - ); - - libraryProjects.data["referenceFrom"] = CONSTANTS.common.LINK; - } else if ( - (requestedData.programId && requestedData.programId !== "") || - (requestedData.programName && requestedData.programName !== "") - ) { - let programAndSolutionInformation = - await this.createProgramAndSolution( - requestedData.programId, - requestedData.programName, - requestedData.entityId ? [requestedData.entityId] : "", - userToken - ); + /** + * generate project certificate. + * @method + * @name generateCertificate + * @param {Object} data - project data for certificate creation data. + * @returns {JSON} certificate details. + */ - if (!programAndSolutionInformation.success) { - return resolve(programAndSolutionInformation); - } + static generateCertificate(data) { + return new Promise(async (resolve, reject) => { + try { - if ( - libraryProjects.data["entityInformation"] && - libraryProjects.data["entityInformation"].entityType !== - programAndSolutionInformation.data.solutionInformation.entityType - ) { - throw { - message: CONSTANTS.apiResponses.ENTITY_TYPE_MIS_MATCHED, - status: HTTP_STATUS_CODE["bad_request"].status, - }; - } + // check eligibility of project for certificate creation + let eligibility = await this.checkCertificateEligibility(data); + if (!eligibility ){ + throw { + message: CONSTANTS.apiResponses.NOT_ELIGIBLE_FOR_CERTIFICATE + }; + } - libraryProjects.data = _.merge( - libraryProjects.data, - programAndSolutionInformation.data - ); - } - // <- Add certificate template data - if ( - libraryProjects.data.certificateTemplateId && - libraryProjects.data.certificateTemplateId !== "" - ) { - // <- Add certificate template details to projectCreation data if present -> - const certificateTemplateDetails = - await certificateTemplateQueries.certificateTemplateDocument({ - _id: libraryProjects.data.certificateTemplateId, - }); + // create payload for certificate generation + const certificateData = await this.createCertificatePayload(data); + + // call sunbird-RC to create certificate for project + const certificate = await this.createCertificate(certificateData, data._id) + + return resolve(certificate); - // create certificate object and add data if certificate template is present. - if (certificateTemplateDetails.length > 0) { - libraryProjects.data["certificate"] = _.pick( - certificateTemplateDetails[0], - ["templateUrl", "status", "criteria"] - ); - } - libraryProjects.data["certificate"]["templateId"] = - libraryProjects.data.certificateTemplateId; - delete libraryProjects.data.certificateTemplateId; - } + } catch (error) { + return resolve({ + success: false, + message: error.message - //Fetch user profile information by calling sunbird's user read api. - let addReportInfoToSolution = false; - let userProfile = await userProfileService.profile(userToken, userId); - if ( - userProfile.success && - userProfile.data && - userProfile.data.response - ) { - libraryProjects.data.userProfile = userProfile.data.response; - addReportInfoToSolution = true; - } + }); + } + }) + } - libraryProjects.data.userId = - libraryProjects.data.updatedBy = - libraryProjects.data.createdBy = - userId; - libraryProjects.data.lastDownloadedAt = new Date(); - libraryProjects.data.status = CONSTANTS.common.STARTED; + /** + * check project eligibility for certificate. + * @method + * @name checkCertificateEligibility + * @param {Object} data - project data for certificate creation data. + * @returns {Boolean} certificate eligibilty status. + */ - if (requestedData.startDate) { - libraryProjects.data.startDate = requestedData.startDate; - } + static checkCertificateEligibility(data) { + return new Promise(async (resolve, reject) => { + try { + let eligible = false; + let updateObject = { + "$set" : {} + }; + // validate certificate data, checking if it passes all criteria + let validateCriteria = await certificateValidationsHelper.criteriaValidation(data) + if ( validateCriteria.success ) { + eligible = true; + } else { + updateObject["$set"]["certificate.message"] = validateCriteria.message; + } + updateObject["$set"]["certificate.eligible"] = eligible; + + // update project certificate data + await projectQueries.findOneAndUpdate( + { + _id: data._id + }, + updateObject + ); + + return resolve(eligible); + } catch (error) { + return resolve({ + success: false, + message: error.message - if (requestedData.endDate) { - libraryProjects.data.endDate = requestedData.endDate; - } + }); + } + }) + } - if (requestedData.hasAcceptedTAndC) { - libraryProjects.data.hasAcceptedTAndC = true; - } + /** + * createCertificatePayload. + * @method + * @name createCertificatePayload + * @param {Object} data - project data for certificate creation data. + * @returns {Object} payload for certificate creation. + */ - libraryProjects.data.projectTemplateId = libraryProjects.data._id; - libraryProjects.data.projectTemplateExternalId = - libraryProjects.data.externalId; + static createCertificatePayload(data) { + return new Promise(async (resolve, reject) => { + try { + console.log("Certificate issuer Kid: ",CERTIFICATE_ISSUER_KID) + + if(data.title.length > 75) { + data.title = data.title.substring(0, 75) + '...'; + } + + // get downloadable url for certificate template + if ( data.certificate.templateUrl && data.certificate.templateUrl !== "" ) { + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: [data.certificate.templateUrl] + } + ); + if ( certificateTemplateDownloadableUrl.success ) { + data.certificate.templateUrl = certificateTemplateDownloadableUrl.data[0].url; + } else { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; + } + } - let projectCreation = await database.models.projects.create( - _.omit(libraryProjects.data, ["_id"]) - ); + let certificateTemplateDetails =[]; + if ( data.certificate.templateId && data.certificate.templateId !== "" ) { + certificateTemplateDetails = await certificateTemplateQueries.certificateTemplateDocument({ + _id : data.certificate.templateId + },["issuer","solutionId","programId"]); + + //certificate template data do not exists. + if ( !certificateTemplateDetails.length > 0 ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND + }; + } + certificateTemplateDetails[0].issuer.kid = CERTIFICATE_ISSUER_KID; + } + + //create certificate request body + let certificateData = { + recipient : { + id : data.userId, + name : `${data.userProfile.firstName} ${data.userProfile.lastName}`, + type : data.userProfile.profileUserType.type + }, + templateUrl : data.certificate.templateUrl, + issuer : certificateTemplateDetails[0].issuer, + status : data.certificate.status.toUpperCase(), + projectId : (data._id).toString(), + projectName : data.title, + programId : (certificateTemplateDetails[0].programId).toString(), + programName : ( data.programInformation && data.programInformation.name ) ? data.programInformation.name : "", + solutionId : (certificateTemplateDetails[0].solutionId).toString(), + solutionName : ( data.solutionInformation && data.solutionInformation.name ) ? data.solutionInformation.name : "", + completedDate : data.completedDate + }; + return resolve(certificateData); - if (addReportInfoToSolution && projectCreation._doc.solutionId) { - let updateSolution = - await solutionsHelper.addReportInformationInSolution( - projectCreation._doc.solutionId, - projectCreation._doc.userProfile - ); - } + } catch (error) { + console.log("error:",error.message) + return resolve({ + success: false, + message: error.message - await kafkaProducersHelper.pushProjectToKafka(projectCreation); + }); + } + }) + } - if (requestedData.rating && requestedData.rating > 0) { - await projectTemplatesHelper.ratings( - projectTemplateId, - requestedData.rating, - userToken - ); - } + /** + * call sunbird-RC for certificate creation. + * @method + * @name createCertificate + * @param {Object} certificateData - payload for certificate creation data. + * @param {string} projectId - project Id. + * @returns {Boolean} certificate creation status. + */ - projectCreation = await _projectInformation(projectCreation._doc); + static createCertificate(certificateData, projectId) { + return new Promise(async (resolve, reject) => { + try { - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: projectCreation.data, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {}, - }); - } - }); - } + const certificateDetails = await certificateService.createCertificate( certificateData ); + + if ( !certificateDetails.success || !certificateDetails.data || !certificateDetails.data.ProjectCertificate ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED + }; + } + + let updateObject = { + "$set" : {} + }; - /** - * get project details. - * @method - * @name userProject - * @param {String} projectId - project id. - * @returns {Object} Project details. - */ + // if transaction id is present. + if ( certificateDetails.data.ProjectCertificate.transactionId && + certificateDetails.data.ProjectCertificate.transactionId !== "" + ) { + let transactionIdvalue = certificateDetails.data.ProjectCertificate.transactionId; + const first2 = transactionIdvalue.slice(0, 2); + + if ( first2 === "1-" ) { + transactionIdvalue = transactionIdvalue.split(/1-(.*)/s) + updateObject["$set"]["certificate.transactionId"] = transactionIdvalue[1]; + } else { + updateObject["$set"]["certificate.transactionId"] = transactionIdvalue; + } + + } - static userProject(projectId) { - return new Promise(async (resolve, reject) => { - try { - const projectDetails = await projectQueries.projectDocument( - { - _id: projectId, - }, - "all" - ); - - if (!projectDetails.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, - }; - } + // update project details certificate details + if ( certificateDetails.data.ProjectCertificate.osid && + certificateDetails.data.ProjectCertificate.osid !== "" + ) { + updateObject["$set"]["certificate.osid"] = certificateDetails.data.ProjectCertificate.osid; + updateObject["$set"]["certificate.issuedOn"] = new Date(); + } + updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date();; + + if ( Object.keys(updateObject["$set"]).length > 0 ) { + let updatedProject = await projectQueries.findOneAndUpdate( + { + _id: projectId + }, + updateObject + ); + } + return resolve( { + success: true + }); + } catch (error) { + return resolve({ + success: false, + message: error.message - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_DETAILS_FETCHED, - data: projectDetails[0], - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {}, - }); - } - }); - } + }); + } + }) + } - /** - * generate project certificate. - * @method - * @name generateCertificate - * @param {Object} data - project data for certificate creation data. - * @returns {JSON} certificate details. - */ + /** + * certificate callback + * @method + * @name certificateCallback + * @param {String} transactionId - transactionId for create certificate. + * @param {String} osid - osid for created certificate. + * @returns {JSON} certificate data updation details. + */ - static generateCertificate(data) { - return new Promise(async (resolve, reject) => { - try { - // check eligibility of project for certificate creation - let eligibility = await this.checkCertificateEligibility(data); - if (!eligibility) { - throw { - message: CONSTANTS.apiResponses.NOT_ELIGIBLE_FOR_CERTIFICATE, - }; - } + static certificateCallback(transactionId, osid) { + return new Promise(async (resolve, reject) => { + try { + // adding comments to check call back is called properly or not + console.log("<==================callback called====================>",transactionId,osid) + console.log("transactionId :",transactionId) + console.log("osid :",osid) + console.log("<==================callback called====================>") + // callback request structure nested so validating transactionId and osid here instead in validator. + if ( transactionId == "" || osid == "" ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.TRANSACTION_ID_AND_OSID_REQUIRED + } + } + let updateObject = { + "$set" : {} + }; - // create payload for certificate generation - const certificateData = await this.createCertificatePayload(data); + // update osid and eligibility based on transactionId + updateObject["$set"]["certificate.osid"] = osid; + updateObject["$set"]["certificate.message"] = CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY; + updateObject["$set"]["certificate.issuedOn"] = new Date(); - // call sunbird-RC to create certificate for project - const certificate = await this.createCertificate( - certificateData, - data._id - ); + let projectDetails = await projectQueries.findOneAndUpdate( + { + "certificate.transactionId" : transactionId + }, + updateObject + ); - return resolve(certificate); - } catch (error) { - return resolve({ - success: false, - message: error.message, - }); - } - }); - } + if ( projectDetails == null || !Object.keys(projectDetails).length > 0 ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND + } + } + await kafkaProducersHelper.pushProjectToKafka(projectDetails); + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, + data : { + _id : ObjectId(projectDetails._id) + } - /** - * check project eligibility for certificate. - * @method - * @name checkCertificateEligibility - * @param {Object} data - project data for certificate creation data. - * @returns {Boolean} certificate eligibilty status. - */ + }); - static checkCertificateEligibility(data) { - return new Promise(async (resolve, reject) => { - try { - let eligible = false; - let updateObject = { - $set: {}, - }; - // validate certificate data, checking if it passes all criteria - let validateCriteria = - await certificateValidationsHelper.criteriaValidation(data); - if (validateCriteria.success) { - eligible = true; - } else { - updateObject["$set"]["certificate.message"] = - validateCriteria.message; - } - updateObject["$set"]["certificate.eligible"] = eligible; + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } - // update project certificate data - await projectQueries.findOneAndUpdate( - { - _id: data._id, - }, - updateObject - ); + /** + * List user project details with certificate + * @method + * @name certificates + * @param {String} userId - userId. + * @returns {JSON} certificate data updation details. + */ - return resolve(eligible); - } catch (error) { - return resolve({ - success: false, - message: error.message, - }); - } - }); - } + static certificates(userId) { + return new Promise(async (resolve, reject) => { + try { + + // get project details of user which have certificate. + const userProject = await projectQueries.projectDocument({ + userId: userId, + status: CONSTANTS.common.SUBMITTED_STATUS, + certificate: {$exists:true} + }, [ + "_id", + "title", + "status", + "certificate.osid", + "certificate.transactioId", + "certificate.templateUrl", + "certificate.status", + "certificate.eligible", + "certificate.message", + "certificate.issuedOn", + "completedDate" + ]); + + if ( !userProject.length > 0 ) { + throw { + status: HTTP_STATUS_CODE["bad_request"].status, + message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND + } + } + let templateFilePath = []; + //loop through user projects and get downloadable url for templateUrl if osid is present. + for( let userProjectPointer = 0; userProjectPointer < userProject.length; userProjectPointer++ ) { + if ( userProject[userProjectPointer].certificate.osid && + userProject[userProjectPointer].certificate.osid !== "" && + userProject[userProjectPointer].certificate.templateUrl && + userProject[userProjectPointer].certificate.templateUrl !== "" + ) { + templateFilePath.push(userProject[userProjectPointer].certificate.templateUrl); + } + } + + if( templateFilePath.length > 0 ) { + + let certificateTemplateDownloadableUrl = + await coreService.getDownloadableUrl( + { + filePaths: templateFilePath + } + ); + if ( !certificateTemplateDownloadableUrl.success ) { + throw { + message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND + }; + } + // map downloadable templateUrl to corresponding project data + userProject.forEach(projectData => { + var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find(item=> item.filePath == projectData.certificate.templateUrl); + if (itemFromUrlArray) { + projectData.certificate.templateUrl = itemFromUrlArray.url; + } + } + ) + } - /** - * createCertificatePayload. - * @method - * @name createCertificatePayload - * @param {Object} data - project data for certificate creation data. - * @returns {Object} payload for certificate creation. - */ + let count = _.countBy(userProject, (rec) => { + return (rec.certificate && rec.certificate.osid && rec.certificate.osid !== "" )? 'generated': 'notGenerated'; + }); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECTS_FETCHED, + data : { + data : userProject, + count : userProject.length, + certificateCount : count.generated + } - static createCertificatePayload(data) { - return new Promise(async (resolve, reject) => { - try { - console.log("Certificate issuer Kid: ", CERTIFICATE_ISSUER_KID); + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } - if (data.title.length > 75) { - data.title = data.title.substring(0, 75) + "..."; - } + /** + * Re-Issue project certificate + * @method + * @name certificateReIssue + * @param {String} projectId - projectId. + * @returns {JSON} certificate re-issued details. + */ - // get downloadable url for certificate template - if ( - data.certificate.templateUrl && - data.certificate.templateUrl !== "" - ) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl({ - filePaths: [data.certificate.templateUrl], - }); - if (certificateTemplateDownloadableUrl.success) { - data.certificate.templateUrl = - certificateTemplateDownloadableUrl.data[0].url; - } else { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND, - }; - } - } + static certificateReIssue(projectId) { + return new Promise(async (resolve, reject) => { + try { + // get project details project for which certificate re-issue required . + const userProject = await projectQueries.projectDocument({ + _id: projectId, + status: CONSTANTS.common.SUBMITTED_STATUS, + certificate: {$exists:true} + }); - let certificateTemplateDetails = []; - if (data.certificate.templateId && data.certificate.templateId !== "") { - certificateTemplateDetails = - await certificateTemplateQueries.certificateTemplateDocument( - { - _id: data.certificate.templateId, - }, - ["issuer", "solutionId", "programId"] - ); + // if project details not found. + if (!userProject.length > 0) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND + }; + } + let updateObject = { + "$set" : {} + }; + + // fetch user data using userId of project and calling the profile API + let userProfileData = await userProfileService.profileReadPrivate(userProject[0].userId); + if ( userProfileData.success && + userProfileData.data && + userProfileData.data.response && + userProfileData.data.response.firstName && + userProfileData.data.response.firstName !== "" + ) { + userProject[0].userProfile.firstName = userProfileData.data.response.firstName; + userProject[0].userProfile.lastName = userProfileData.data.response.lastName; + } else { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND + }; + } - //certificate template data do not exists. - if (!certificateTemplateDetails.length > 0) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND, - }; - } - certificateTemplateDetails[0].issuer.kid = CERTIFICATE_ISSUER_KID; - } + // create payload for certificate generation + const certificateData = await this.createCertificatePayload(userProject[0]); - //create certificate request body - let certificateData = { - recipient: { - id: data.userId, - name: `${data.userProfile.firstName} ${data.userProfile.lastName}`, - type: data.userProfile.profileUserType.type, - }, - templateUrl: data.certificate.templateUrl, - issuer: certificateTemplateDetails[0].issuer, - status: data.certificate.status.toUpperCase(), - projectId: data._id.toString(), - projectName: data.title, - programId: certificateTemplateDetails[0].programId.toString(), - programName: - data.programInformation && data.programInformation.name - ? data.programInformation.name - : "", - solutionId: certificateTemplateDetails[0].solutionId.toString(), - solutionName: - data.solutionInformation && data.solutionInformation.name - ? data.solutionInformation.name - : "", - completedDate: data.completedDate, - }; - return resolve(certificateData); - } catch (error) { - console.log("error:", error.message); - return resolve({ - success: false, - message: error.message, - }); - } - }); - } + // call sunbird-RC to create certificate for project + const certificate = await this.createCertificate(certificateData, userProject[0]._id); - /** - * call sunbird-RC for certificate creation. - * @method - * @name createCertificate - * @param {Object} certificateData - payload for certificate creation data. - * @param {string} projectId - project Id. - * @returns {Boolean} certificate creation status. - */ + if ( !certificate.success ) { + throw { + message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED + }; + } - static createCertificate(certificateData, projectId) { - return new Promise(async (resolve, reject) => { - try { - const certificateDetails = await certificateService.createCertificate( - certificateData - ); - - if ( - !certificateDetails.success || - !certificateDetails.data || - !certificateDetails.data.ProjectCertificate - ) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED, - }; - } + if ( userProject[0].certificate.transactionId ) { + updateObject["$set"]["certificate.originalTransactionInformation.transactionId"] = userProject[0].certificate.transactionId + } + if ( userProject[0].certificate.osid ) { + updateObject["$set"]["certificate.originalTransactionInformation.osid"] = userProject[0].certificate.osid; + } - let updateObject = { - $set: {}, - }; - - // if transaction id is present. - if ( - certificateDetails.data.ProjectCertificate.transactionId && - certificateDetails.data.ProjectCertificate.transactionId !== "" - ) { - let transactionIdvalue = - certificateDetails.data.ProjectCertificate.transactionId; - const first2 = transactionIdvalue.slice(0, 2); - - if (first2 === "1-") { - transactionIdvalue = transactionIdvalue.split(/1-(.*)/s); - updateObject["$set"]["certificate.transactionId"] = - transactionIdvalue[1]; - } else { - updateObject["$set"]["certificate.transactionId"] = - transactionIdvalue; - } - } + if (userProject[0].userProfile.firstName ) { + updateObject["$set"]["userProfile.firstName"] = userProject[0].userProfile.firstName; + } - // update project details certificate details - if ( - certificateDetails.data.ProjectCertificate.osid && - certificateDetails.data.ProjectCertificate.osid !== "" - ) { - updateObject["$set"]["certificate.osid"] = - certificateDetails.data.ProjectCertificate.osid; - updateObject["$set"]["certificate.issuedOn"] = new Date(); - } - updateObject["$set"]["certificate.transactionIdCreatedAt"] = new Date(); + if (userProject[0].userProfile.lastName ) { + updateObject["$set"]["userProfile.lastName"] = userProject[0].userProfile.lastName; + } - if (Object.keys(updateObject["$set"]).length > 0) { - let updatedProject = await projectQueries.findOneAndUpdate( - { - _id: projectId, - }, - updateObject - ); - } - return resolve({ - success: true, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - }); - } - }); - } + updateObject["$set"]["certificate.reIssuedAt"] = new Date(); + await projectQueries.findOneAndUpdate( + { + _id: userProject[0]._id + }, + updateObject + ); + + return resolve({ + success: true, + message: CONSTANTS.apiResponses.PROJECT_SUBMITTED_FOR_REISSUE, + data : { + _id : userProject[0]._id + } - /** - * certificate callback - * @method - * @name certificateCallback - * @param {String} transactionId - transactionId for create certificate. - * @param {String} osid - osid for created certificate. - * @returns {JSON} certificate data updation details. - */ + }); + } catch (error) { + return resolve({ + success: false, + message: error.message, + data: {} + }); + } + }) + } + + +}; + +/** + * Project information. + * @method + * @name _projectInformation + * @param {Object} project - Project data. + * @returns {Object} Project information. +*/ + +function _projectInformation(project) { - static certificateCallback(transactionId, osid) { return new Promise(async (resolve, reject) => { - try { - // adding comments to check call back is called properly or not - console.log( - "<==================callback called====================>", - transactionId, - osid - ); - console.log("transactionId :", transactionId); - console.log("osid :", osid); - console.log("<==================callback called====================>"); - // callback request structure nested so validating transactionId and osid here instead in validator. - if (transactionId == "" || osid == "") { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.TRANSACTION_ID_AND_OSID_REQUIRED, - }; - } - let updateObject = { - $set: {}, - }; + try { + + if (project.entityInformation) { + project.entityId = project.entityInformation._id; + project.entityName = project.entityInformation.name; + } - // update osid and eligibility based on transactionId - updateObject["$set"]["certificate.osid"] = osid; - updateObject["$set"]["certificate.message"] = - CONSTANTS.common.PROJECT_CERTIFICATE_GENERATED_SUCCESSFULLY; - updateObject["$set"]["certificate.issuedOn"] = new Date(); + if (project.programInformation) { + project.programId = project.programInformation._id; + project.programName = project.programInformation.name; + } + + //project attachments + if ( project.attachments && project.attachments.length > 0 ) { + + let projectLinkAttachments = []; + let projectAttachments = []; + + for ( + let pointerToAttachment = 0; + pointerToAttachment < project.attachments.length; + pointerToAttachment++ + ) { - let projectDetails = await projectQueries.findOneAndUpdate( - { - "certificate.transactionId": transactionId, - }, - updateObject - ); - - if (projectDetails == null || !Object.keys(projectDetails).length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND, - }; + let currentProjectAttachment = project.attachments[pointerToAttachment]; + if ( currentProjectAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { + projectLinkAttachments.push(currentProjectAttachment); + } else { + projectAttachments.push(currentProjectAttachment.sourcePath); + } + } + + let projectAttachmentsUrl = await _attachmentInformation(projectAttachments, projectLinkAttachments, project.attachments, CONSTANTS.common.PROJECT_ATTACHMENT); + if ( projectAttachmentsUrl.data && projectAttachmentsUrl.data.length > 0 ) { + project.attachments = projectAttachmentsUrl.data; + } + + } + + //task attachments + if (project.tasks && project.tasks.length > 0) { + //order task based on task sequence + if ( project.taskSequence && project.taskSequence.length > 0 ) { + project.tasks = taskArrayBySequence(project.tasks, project.taskSequence, 'externalId'); + } + + let attachments = []; + let mapTaskIdToAttachment = {}; + let mapLinkAttachment = {}; + + for (let task = 0; task < project.tasks.length; task++) { + + let currentTask = project.tasks[task]; + + if (currentTask.attachments && currentTask.attachments.length > 0) { + for ( + let attachment = 0; + attachment < currentTask.attachments.length; + attachment++ + ) { + let currentAttachment = currentTask.attachments[attachment]; + + if (currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { + if (!Array.isArray(mapLinkAttachment[currentTask._id]) || !mapLinkAttachment[currentTask._id].length ) { + mapLinkAttachment[currentTask._id] = []; + } + mapLinkAttachment[currentTask._id].push(currentAttachment); + } else { + attachments.push(currentAttachment.sourcePath); + } + + if (!mapTaskIdToAttachment[currentAttachment.sourcePath] && currentAttachment.type != CONSTANTS.common.ATTACHMENT_TYPE_LINK ) { + mapTaskIdToAttachment[currentAttachment.sourcePath] = { + taskId: currentTask._id + }; + } + } + } + } + + let taskAttachmentsUrl = await _attachmentInformation(attachments, mapLinkAttachment, [], CONSTANTS.common.TASK_ATTACHMENT, mapTaskIdToAttachment, project.tasks); + if ( taskAttachmentsUrl.data && taskAttachmentsUrl.data.length > 0 ) { + project.tasks = taskAttachmentsUrl.data; + } + } + + project.status = + project.status ? project.status : CONSTANTS.common.NOT_STARTED_STATUS; + + if (project.metaInformation) { + Object.keys(project.metaInformation).forEach(projectMetaKey => { + project[projectMetaKey] = project.metaInformation[projectMetaKey]; + }); + } + + delete project.metaInformation; + delete project.__v; + delete project.entityInformation; + delete project.solutionInformation; + delete project.programInformation; + + return resolve({ + success: true, + data: project + }); + + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) } - await kafkaProducersHelper.pushProjectToKafka(projectDetails); - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_CERTIFICATE_GENERATED, - data: { - _id: ObjectId(projectDetails._id), - }, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {}, - }); - } - }); - } + }) +} - /** - * List user project details with certificate - * @method - * @name certificates - * @param {String} userId - userId. - * @returns {JSON} certificate data updation details. - */ +function taskArrayBySequence (taskArray, sequenceArray, key) { + var map = sequenceArray.reduce((acc, value, index) => (acc[value] = index + 1, acc), {}) + const sortedTaskArray = taskArray.sort((a, b) => (map[a[key]] || Infinity) - (map[b[key]] || Infinity)) + return sortedTaskArray +}; - static certificates(userId) { +/** + * Attachment information of project. + * @method + * @name _attachmentInformation + * @param {Array} attachments - attachments data. + * @param {String} type - project or task attachement. + * @returns {Object} Project attachments. +*/ +function _attachmentInformation ( attachmentWithSourcePath = [], linkAttachments = [], attachments = [] , type, mapTaskIdToAttachment = {}, tasks = []) { return new Promise(async (resolve, reject) => { - try { - // get project details of user which have certificate. - const userProject = await projectQueries.projectDocument( - { - userId: userId, - status: CONSTANTS.common.SUBMITTED_STATUS, - certificate: { $exists: true }, - }, - [ - "_id", - "title", - "status", - "certificate.osid", - "certificate.transactioId", - "certificate.templateUrl", - "certificate.status", - "certificate.eligible", - "certificate.message", - "certificate.issuedOn", - "completedDate", - ] - ); - - if (!userProject.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND, - }; - } - let templateFilePath = []; - //loop through user projects and get downloadable url for templateUrl if osid is present. - for ( - let userProjectPointer = 0; - userProjectPointer < userProject.length; - userProjectPointer++ - ) { - if ( - userProject[userProjectPointer].certificate.osid && - userProject[userProjectPointer].certificate.osid !== "" && - userProject[userProjectPointer].certificate.templateUrl && - userProject[userProjectPointer].certificate.templateUrl !== "" - ) { - templateFilePath.push( - userProject[userProjectPointer].certificate.templateUrl - ); - } - } + try { - if (templateFilePath.length > 0) { - let certificateTemplateDownloadableUrl = - await coreService.getDownloadableUrl({ - filePaths: templateFilePath, - }); - if (!certificateTemplateDownloadableUrl.success) { - throw { - message: CONSTANTS.apiResponses.DOWNLOADABLE_URL_NOT_FOUND, - }; - } - // map downloadable templateUrl to corresponding project data - userProject.forEach((projectData) => { - var itemFromUrlArray = certificateTemplateDownloadableUrl.data.find( - (item) => item.filePath == projectData.certificate.templateUrl - ); - if (itemFromUrlArray) { - projectData.certificate.templateUrl = itemFromUrlArray.url; + let attachmentOrTask = []; + + if ( attachmentWithSourcePath && attachmentWithSourcePath.length > 0 ) { + + let attachmentsUrl = + await coreService.getDownloadableUrl( + { + filePaths: attachmentWithSourcePath + } + ); + + if (!attachmentsUrl.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND + } + } + + if ( attachmentsUrl.data && attachmentsUrl.data.length > 0) { + + if (type === CONSTANTS.common.PROJECT_ATTACHMENT ) { + + attachmentsUrl.data.forEach(eachAttachment => { + + let projectAttachmentIndex = + attachments.findIndex(attachmentData => attachmentData.sourcePath == eachAttachment.filePath); + + if (projectAttachmentIndex > -1) { + attachments[projectAttachmentIndex].url = eachAttachment.url; + } + }) + + } else { + + attachmentsUrl.data.forEach(taskAttachments => { + + let taskIndex = + tasks.findIndex(task => task._id === mapTaskIdToAttachment[taskAttachments.filePath].taskId); + + if (taskIndex > -1) { + + let attachmentIndex = + tasks[taskIndex].attachments.findIndex(attachment => attachment.sourcePath === taskAttachments.filePath); + + if (attachmentIndex > -1) { + tasks[taskIndex].attachments[attachmentIndex].url = taskAttachments.url; + } + } + }) + } + } } - }); - } - let count = _.countBy(userProject, (rec) => { - return rec.certificate && - rec.certificate.osid && - rec.certificate.osid !== "" - ? "generated" - : "notGenerated"; - }); + if ( linkAttachments && linkAttachments.length > 0 ) { + + if (type === CONSTANTS.common.PROJECT_ATTACHMENT ) { + attachments.concat(linkAttachments); + + + } else { + + Object.keys(linkAttachments).forEach(eachTaskId => { + + let taskIdIndex = tasks.findIndex(task => task._id === eachTaskId); + if ( taskIdIndex > -1 ) { + tasks[taskIdIndex].attachments.concat(linkAttachments[eachTaskId]); + } + }) + + } + } + + attachmentOrTask = (type === CONSTANTS.common.PROJECT_ATTACHMENT) ? attachments : tasks + + return resolve({ + success: true, + data: attachmentOrTask + }); + + } catch (error) { return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECTS_FETCHED, - data: { - data: userProject, - count: userProject.length, - certificateCount: count.generated, - }, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {}, - }); - } - }); - } + message: error.message, + success: false, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }) + } - /** - * Re-Issue project certificate - * @method - * @name certificateReIssue - * @param {String} projectId - projectId. - * @returns {JSON} certificate re-issued details. - */ + }) +} - static certificateReIssue(projectId) { - return new Promise(async (resolve, reject) => { - try { - // get project details project for which certificate re-issue required . - const userProject = await projectQueries.projectDocument({ - _id: projectId, - status: CONSTANTS.common.SUBMITTED_STATUS, - certificate: { $exists: true }, - }); +/** + * Task of project. + * @method + * @name _projectTask + * @param {Array} tasks - tasks data. + * @param {String} userId - logged in user id. + * @returns {Object} Project task. +*/ - // if project details not found. - if (!userProject.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND, - }; - } - let updateObject = { - $set: {}, - }; - - // fetch user data using userId of project and calling the profile API - let userProfileData = await userProfileService.profileReadPrivate( - userProject[0].userId - ); - if ( - userProfileData.success && - userProfileData.data && - userProfileData.data.response && - userProfileData.data.response.firstName && - userProfileData.data.response.firstName !== "" - ) { - userProject[0].userProfile.firstName = - userProfileData.data.response.firstName; - userProject[0].userProfile.lastName = - userProfileData.data.response.lastName; - } else { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.USER_PROFILE_NOT_FOUND, - }; - } +function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { - // create payload for certificate generation - const certificateData = await this.createCertificatePayload( - userProject[0] - ); - - // call sunbird-RC to create certificate for project - const certificate = await this.createCertificate( - certificateData, - userProject[0]._id - ); - - if (!certificate.success) { - throw { - message: CONSTANTS.apiResponses.CERTIFICATE_GENERATION_FAILED, - }; - } + tasks.forEach(singleTask => { + + singleTask.externalId = singleTask.externalId ? singleTask.externalId : singleTask.name.toLowerCase(); + singleTask.type = singleTask.type ? singleTask.type : CONSTANTS.common.SIMPLE_TASK_TYPE; + singleTask.status = singleTask.status ? singleTask.status : CONSTANTS.common.NOT_STARTED_STATUS; + singleTask.isDeleted = singleTask.isDeleted ? singleTask.isDeleted : false; - if (userProject[0].certificate.transactionId) { - updateObject["$set"][ - "certificate.originalTransactionInformation.transactionId" - ] = userProject[0].certificate.transactionId; + if (!singleTask.hasOwnProperty("isDeletable")) { + singleTask.isDeletable = true; } - if (userProject[0].certificate.osid) { - updateObject["$set"][ - "certificate.originalTransactionInformation.osid" - ] = userProject[0].certificate.osid; + if ( UTILS.isValidMongoId(singleTask._id.toString()) ) { + singleTask.referenceId = singleTask._id.toString(); } - - if (userProject[0].userProfile.firstName) { - updateObject["$set"]["userProfile.firstName"] = - userProject[0].userProfile.firstName; + singleTask.createdAt = singleTask.createdAt ? singleTask.createdAt : new Date(); + singleTask.updatedAt = new Date(); + singleTask._id = UTILS.isValidMongoId(singleTask._id.toString()) ? uuidv4() : singleTask._id; + singleTask.isImportedFromLibrary = isImportedFromLibrary; + singleTask.syncedAt = new Date(); + + if (singleTask.startDate) { + singleTask.startDate = singleTask.startDate; } - if (userProject[0].userProfile.lastName) { - updateObject["$set"]["userProfile.lastName"] = - userProject[0].userProfile.lastName; + if (singleTask.endDate) { + singleTask.endDate = singleTask.endDate; } - updateObject["$set"]["certificate.reIssuedAt"] = new Date(); - await projectQueries.findOneAndUpdate( - { - _id: userProject[0]._id, - }, - updateObject - ); + if (singleTask.visibleIf && singleTask.visibleIf.length > 0) { - return resolve({ - success: true, - message: CONSTANTS.apiResponses.PROJECT_SUBMITTED_FOR_REISSUE, - data: { - _id: userProject[0]._id, - }, - }); - } catch (error) { - return resolve({ - success: false, - message: error.message, - data: {}, + if (parentTaskId !== "") { + singleTask.visibleIf.forEach(task => { + task._id = parentTaskId; + }); + } + } + + removeFieldsFromRequest.forEach((removeField) => { + delete singleTask[removeField]; }); - } - }); - } -}; - -/** - * Project information. - * @method - * @name _projectInformation - * @param {Object} project - Project data. - * @returns {Object} Project information. - */ + + if (singleTask.children) { + _projectTask( + singleTask.children, + isImportedFromLibrary, + singleTask._id + ); + } else { + singleTask.children = []; + } -function _projectInformation(project) { - return new Promise(async (resolve, reject) => { - try { - if (project.entityInformation) { - project.entityId = project.entityInformation._id; - project.entityName = project.entityInformation.name; - } + }) + + return tasks; +} - if (project.programInformation) { - project.programId = project.programInformation._id; - project.programName = project.programInformation.name; - } +/** + * Project categories information. + * @method + * @name _projectCategories + * @param {Array} categories - Categories data. + * @returns {Object} Project categories information. +*/ - //project attachments - if (project.attachments && project.attachments.length > 0) { - let projectLinkAttachments = []; - let projectAttachments = []; - - for ( - let pointerToAttachment = 0; - pointerToAttachment < project.attachments.length; - pointerToAttachment++ - ) { - let currentProjectAttachment = - project.attachments[pointerToAttachment]; - if ( - currentProjectAttachment.type == - CONSTANTS.common.ATTACHMENT_TYPE_LINK - ) { - projectLinkAttachments.push(currentProjectAttachment); - } else { - projectAttachments.push(currentProjectAttachment.sourcePath); - } - } +function _projectCategories(categories) { + return new Promise(async (resolve, reject) => { + try { - let projectAttachmentsUrl = await _attachmentInformation( - projectAttachments, - projectLinkAttachments, - project.attachments, - CONSTANTS.common.PROJECT_ATTACHMENT - ); - if ( - projectAttachmentsUrl.data && - projectAttachmentsUrl.data.length > 0 - ) { - project.attachments = projectAttachmentsUrl.data; - } - } + let categoryIds = []; - //task attachments - if (project.tasks && project.tasks.length > 0) { - //order task based on task sequence - if (project.taskSequence && project.taskSequence.length > 0) { - project.tasks = taskArrayBySequence( - project.tasks, - project.taskSequence, - "externalId" - ); - } + categories.forEach(category => { + if (category.value && category.value !== "") { + categoryIds.push(category.value); + } + }); - let attachments = []; - let mapTaskIdToAttachment = {}; - let mapLinkAttachment = {}; + let categoryData = []; - for (let task = 0; task < project.tasks.length; task++) { - let currentTask = project.tasks[task]; + if (categoryIds.length > 0) { - if (currentTask.attachments && currentTask.attachments.length > 0) { - for ( - let attachment = 0; - attachment < currentTask.attachments.length; - attachment++ - ) { - let currentAttachment = currentTask.attachments[attachment]; + categoryData = + await projectCategoriesQueries.categoryDocuments({ + _id: { $in: categoryIds } + }, ["name", "externalId"]); - if ( - currentAttachment.type == CONSTANTS.common.ATTACHMENT_TYPE_LINK - ) { - if ( - !Array.isArray(mapLinkAttachment[currentTask._id]) || - !mapLinkAttachment[currentTask._id].length - ) { - mapLinkAttachment[currentTask._id] = []; - } - mapLinkAttachment[currentTask._id].push(currentAttachment); - } else { - attachments.push(currentAttachment.sourcePath); - } - - if ( - !mapTaskIdToAttachment[currentAttachment.sourcePath] && - currentAttachment.type != CONSTANTS.common.ATTACHMENT_TYPE_LINK - ) { - mapTaskIdToAttachment[currentAttachment.sourcePath] = { - taskId: currentTask._id, - }; - } + if (!categoryData.length > 0) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.CATEGORY_NOT_FOUND + } + } } - } - } - let taskAttachmentsUrl = await _attachmentInformation( - attachments, - mapLinkAttachment, - [], - CONSTANTS.common.TASK_ATTACHMENT, - mapTaskIdToAttachment, - project.tasks - ); - if (taskAttachmentsUrl.data && taskAttachmentsUrl.data.length > 0) { - project.tasks = taskAttachmentsUrl.data; - } - } + let categoryInternalIdToData = {}; - project.status = project.status - ? project.status - : CONSTANTS.common.NOT_STARTED_STATUS; + if (categoryData.length > 0) { - if (project.metaInformation) { - Object.keys(project.metaInformation).forEach((projectMetaKey) => { - project[projectMetaKey] = project.metaInformation[projectMetaKey]; - }); - } + categoryData.forEach(category => { + categoryInternalIdToData[category._id.toString()] = category; + }); + } - delete project.metaInformation; - delete project.__v; - delete project.entityInformation; - delete project.solutionInformation; - delete project.programInformation; + const categoriesData = categories.map(category => { + let categoryData = {}; - return resolve({ - success: true, - data: project, - }); - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - }); - } - }); -} + if ( + category.value && + category.value !== "" && + categoryInternalIdToData[category.value] + ) { + categoryData = categoryInternalIdToData[category.value]; + } else { + categoryData = { + name: category.label, + externalId: "", + _id: "" + } + } -function taskArrayBySequence(taskArray, sequenceArray, key) { - var map = sequenceArray.reduce( - (acc, value, index) => ((acc[value] = index + 1), acc), - {} - ); - const sortedTaskArray = taskArray.sort( - (a, b) => (map[a[key]] || Infinity) - (map[b[key]] || Infinity) - ); - return sortedTaskArray; -} + return categoryData; + }); -/** - * Attachment information of project. - * @method - * @name _attachmentInformation - * @param {Array} attachments - attachments data. - * @param {String} type - project or task attachement. - * @returns {Object} Project attachments. - */ -function _attachmentInformation( - attachmentWithSourcePath = [], - linkAttachments = [], - attachments = [], - type, - mapTaskIdToAttachment = {}, - tasks = [] -) { - return new Promise(async (resolve, reject) => { - try { - let attachmentOrTask = []; - - if (attachmentWithSourcePath && attachmentWithSourcePath.length > 0) { - let attachmentsUrl = await coreService.getDownloadableUrl({ - filePaths: attachmentWithSourcePath, - }); + return resolve({ + success: true, + data: categoriesData + }); - if (!attachmentsUrl.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.ATTACHMENTS_URL_NOT_FOUND, - }; + } catch (error) { + return resolve({ + message: error.message, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + data: {} + }); } + }) +} - if (attachmentsUrl.data && attachmentsUrl.data.length > 0) { - if (type === CONSTANTS.common.PROJECT_ATTACHMENT) { - attachmentsUrl.data.forEach((eachAttachment) => { - let projectAttachmentIndex = attachments.findIndex( - (attachmentData) => - attachmentData.sourcePath == eachAttachment.filePath - ); - - if (projectAttachmentIndex > -1) { - attachments[projectAttachmentIndex].url = eachAttachment.url; - } - }); - } else { - attachmentsUrl.data.forEach((taskAttachments) => { - let taskIndex = tasks.findIndex( - (task) => - task._id === - mapTaskIdToAttachment[taskAttachments.filePath].taskId - ); - - if (taskIndex > -1) { - let attachmentIndex = tasks[taskIndex].attachments.findIndex( - (attachment) => - attachment.sourcePath === taskAttachments.filePath - ); +/** + * Entities information for project. + * @method + * @name _entitiesInformation + * @param {String} entityIds - entity id. + * @returns {Object} Project entity information. +*/ - if (attachmentIndex > -1) { - tasks[taskIndex].attachments[attachmentIndex].url = - taskAttachments.url; +function _entitiesInformation(entityIds) { + return new Promise(async (resolve, reject) => { + try { + let locationIds = []; + let locationCodes = []; + let entityInformations = []; + entityIds.forEach(entity=>{ + if (UTILS.checkValidUUID(entity)) { + locationIds.push(entity); + } else { + locationCodes.push(entity); } - } }); - } - } - } - if (linkAttachments && linkAttachments.length > 0) { - if (type === CONSTANTS.common.PROJECT_ATTACHMENT) { - attachments.concat(linkAttachments); - } else { - Object.keys(linkAttachments).forEach((eachTaskId) => { - let taskIdIndex = tasks.findIndex( - (task) => task._id === eachTaskId - ); - if (taskIdIndex > -1) { - tasks[taskIdIndex].attachments.concat( - linkAttachments[eachTaskId] - ); + if ( locationIds.length > 0 ) { + let bodyData = { + "id" : locationIds + } + let entityData = await userProfileService.locationSearch( bodyData, formatResult = true); + if ( entityData.success ) { + entityInformations = entityData.data; + } } - }); - } - } - attachmentOrTask = - type === CONSTANTS.common.PROJECT_ATTACHMENT ? attachments : tasks; + if ( locationCodes.length > 0 ) { + let bodyData = { + "code" : locationCodes + } + let entityData = await userProfileService.locationSearch( bodyData , formatResult = true ); + if ( entityData.success ) { + entityInformations = entityInformations.concat(entityData.data); + } + } + + if ( !entityInformations.length > 0 ) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND + } + } + let entitiesData = []; + if ( entityInformations.length > 0 ) { + entitiesData = await _entitiesMetaInformation(entityInformations); + } + + return resolve({ + success: true, + data: entitiesData + }); - return resolve({ - success: true, - data: attachmentOrTask, - }); - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - }); - } - }); + } catch (error) { + return resolve({ + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + message: error.message, + data: [] + }); + } + }) } /** - * Task of project. - * @method - * @name _projectTask - * @param {Array} tasks - tasks data. - * @param {String} userId - logged in user id. - * @returns {Object} Project task. - */ + * Assessment details + * @method + * @name _assessmentDetails + * @param {Object} assessmentData - Assessment data. + * @returns {Object} +*/ -function _projectTask(tasks, isImportedFromLibrary = false, parentTaskId = "") { - tasks.forEach((singleTask) => { - singleTask.externalId = singleTask.externalId - ? singleTask.externalId - : singleTask.name.toLowerCase(); - singleTask.type = singleTask.type - ? singleTask.type - : CONSTANTS.common.SIMPLE_TASK_TYPE; - singleTask.status = singleTask.status - ? singleTask.status - : CONSTANTS.common.NOT_STARTED_STATUS; - singleTask.isDeleted = singleTask.isDeleted ? singleTask.isDeleted : false; - - if (!singleTask.hasOwnProperty("isDeletable")) { - singleTask.isDeletable = true; - } - if (UTILS.isValidMongoId(singleTask._id.toString())) { - singleTask.referenceId = singleTask._id.toString(); - } - singleTask.createdAt = singleTask.createdAt - ? singleTask.createdAt - : new Date(); - singleTask.updatedAt = new Date(); - singleTask._id = UTILS.isValidMongoId(singleTask._id.toString()) - ? uuidv4() - : singleTask._id; - singleTask.isImportedFromLibrary = isImportedFromLibrary; - singleTask.syncedAt = new Date(); - - if (singleTask.startDate) { - singleTask.startDate = singleTask.startDate; - } +function _assessmentDetails(assessmentData) { + return new Promise(async (resolve, reject) => { + try { - if (singleTask.endDate) { - singleTask.endDate = singleTask.endDate; - } + let result = {}; - if (singleTask.visibleIf && singleTask.visibleIf.length > 0) { - if (parentTaskId !== "") { - singleTask.visibleIf.forEach((task) => { - task._id = parentTaskId; - }); - } - } + if (assessmentData.project) { - removeFieldsFromRequest.forEach((removeField) => { - delete singleTask[removeField]; - }); + let templateTasks = + await projectTemplateTaskQueries.taskDocuments({ + externalId: assessmentData.project.taskId + }, ["_id"]) - if (singleTask.children) { - _projectTask(singleTask.children, isImportedFromLibrary, singleTask._id); - } else { - singleTask.children = []; - } - }); + if (templateTasks.length > 0) { + assessmentData.project.taskId = templateTasks[0]._id; + } + } - return tasks; -} + if (assessmentData.solutionDetails.isReusable) { + + let createdAssessment = + await surveyService.createAssessmentSolutionFromTemplate( + assessmentData.token, + assessmentData.solutionDetails._id, + { + name: assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), + description: assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), + program: { + _id: assessmentData.programId, + name: "" + }, + entities: [assessmentData.entityId], + project: assessmentData.project + } + ); -/** - * Project categories information. - * @method - * @name _projectCategories - * @param {Array} categories - Categories data. - * @returns {Object} Project categories information. - */ + if (!createdAssessment.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.COULD_NOT_CREATE_ASSESSMENT_SOLUTION + } + } -function _projectCategories(categories) { - return new Promise(async (resolve, reject) => { - try { - let categoryIds = []; + result["solutionId"] = createdAssessment.data._id; - categories.forEach((category) => { - if (category.value && category.value !== "") { - categoryIds.push(category.value); - } - }); + } else { - let categoryData = []; + let assignedAssessmentToUser = + await surveyService.createEntityAssessors( + assessmentData.token, + assessmentData.solutionDetails.programId, + assessmentData.solutionDetails._id, + [assessmentData.entityId] + ); - if (categoryIds.length > 0) { - categoryData = await projectCategoriesQueries.categoryDocuments( - { - _id: { $in: categoryIds }, - }, - ["name", "externalId"] - ); - - if (!categoryData.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.CATEGORY_NOT_FOUND, - }; - } - } + if (!assignedAssessmentToUser.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.FAILED_TO_ASSIGNED_ASSESSMENT_TO_USER + } + } + + let entitiesAddedToSolution = + await surveyService.addEntitiesToSolution( + assessmentData.token, + assessmentData.solutionDetails._id, + [assessmentData.entityId.toString()] + ); - let categoryInternalIdToData = {}; + if (!entitiesAddedToSolution.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.FAILED_TO_ADD_ENTITY_TO_SOLUTION + } + } - if (categoryData.length > 0) { - categoryData.forEach((category) => { - categoryInternalIdToData[category._id.toString()] = category; - }); - } + let solutionUpdated = + await surveyService.updateSolution( + assessmentData.token, + { + "project": assessmentData.project, + referenceFrom: "project" + }, + assessmentData.solutionDetails.externalId + ); - const categoriesData = categories.map((category) => { - let categoryData = {}; + if (!solutionUpdated.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.SOLUTION_NOT_UPDATED + } + } - if ( - category.value && - category.value !== "" && - categoryInternalIdToData[category.value] - ) { - categoryData = categoryInternalIdToData[category.value]; - } else { - categoryData = { - name: category.label, - externalId: "", - _id: "", - }; - } + result["solutionId"] = assessmentData.solutionDetails._id; + } - return categoryData; - }); + return resolve({ + success: true, + data: result + }); - return resolve({ - success: true, - data: categoriesData, - }); - } catch (error) { - return resolve({ - message: error.message, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - data: {}, - }); - } - }); + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }); + } + }) } /** - * Entities information for project. - * @method - * @name _entitiesInformation - * @param {String} entityIds - entity id. - * @returns {Object} Project entity information. - */ + * Observation details + * @method + * @name _observationDetails + * @param {Object} observationData - Observation data. + * @returns {Object} +*/ -function _entitiesInformation(entityIds) { - return new Promise(async (resolve, reject) => { - try { - let locationIds = []; - let locationCodes = []; - let entityInformations = []; - entityIds.forEach((entity) => { - if (UTILS.checkValidUUID(entity)) { - locationIds.push(entity); - } else { - locationCodes.push(entity); - } - }); - - if (locationIds.length > 0) { - let bodyData = { - id: locationIds, - }; - let entityData = await userProfileService.locationSearch( - bodyData, - (formatResult = true) - ); - if (entityData.success) { - entityInformations = entityData.data; - } - } +function _observationDetails(observationData, userRoleAndProfileInformation = {}) { + return new Promise(async (resolve, reject) => { + try { - if (locationCodes.length > 0) { - let bodyData = { - code: locationCodes, - }; - let entityData = await userProfileService.locationSearch( - bodyData, - (formatResult = true) - ); - if (entityData.success) { - entityInformations = entityInformations.concat(entityData.data); - } - } + let result = {}; - if (!entityInformations.length > 0) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND, - }; - } - let entitiesData = []; - if (entityInformations.length > 0) { - entitiesData = await _entitiesMetaInformation(entityInformations); - } + if (observationData.project) { - return resolve({ - success: true, - data: entitiesData, - }); - } catch (error) { - return resolve({ - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - message: error.message, - data: [], - }); - } - }); -} + let templateTasks = + await projectTemplateTaskQueries.taskDocuments({ + externalId: observationData.project.taskId + }, ["_id"]) -/** - * Assessment details - * @method - * @name _assessmentDetails - * @param {Object} assessmentData - Assessment data. - * @returns {Object} - */ + if (templateTasks.length > 0) { + observationData.project.taskId = templateTasks[0]._id; + } + } -function _assessmentDetails(assessmentData) { - return new Promise(async (resolve, reject) => { - try { - let result = {}; + if (observationData.solutionDetails.isReusable) { + + let observationCreatedFromTemplate = + await surveyService.createObservationFromSolutionTemplate( + observationData.token, + observationData.solutionDetails._id, + { + name: observationData.solutionDetails.name + "-" + UTILS.epochTime(), + description: observationData.solutionDetails.name + "-" + UTILS.epochTime(), + program: { + _id: observationData.programId, + name: "" + }, + status: CONSTANTS.common.PUBLISHED_STATUS, + entities: [observationData.entityId], + project: observationData.project + } + ); - if (assessmentData.project) { - let templateTasks = await projectTemplateTaskQueries.taskDocuments( - { - externalId: assessmentData.project.taskId, - }, - ["_id"] - ); + if (!observationCreatedFromTemplate.success) { + throw { + status: HTTP_STATUS_CODE['bad_request'].status, + message: CONSTANTS.apiResponses.OBSERVATION_NOT_CREATED + } + } - if (templateTasks.length > 0) { - assessmentData.project.taskId = templateTasks[0]._id; - } - } + result["solutionId"] = observationCreatedFromTemplate.data._id; + result["observationId"] = observationCreatedFromTemplate.data.observationId; + + } else { - if (assessmentData.solutionDetails.isReusable) { - let createdAssessment = - await surveyService.createAssessmentSolutionFromTemplate( - assessmentData.token, - assessmentData.solutionDetails._id, - { - name: - assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), - description: - assessmentData.solutionDetails.name + "-" + UTILS.epochTime(), - program: { - _id: assessmentData.programId, - name: "", - }, - entities: [assessmentData.entityId], - project: assessmentData.project, + let startDate = new Date(); + let endDate = new Date(); + endDate.setFullYear(endDate.getFullYear() + 1); + + let observation = { + name: observationData.solutionDetails.name, + description: observationData.solutionDetails.name, + status: CONSTANTS.common.PUBLISHED_STATUS, + startDate: startDate, + endDate: endDate, + entities: [observationData.entityId], + project: observationData.project + }; + + let observationCreated = await surveyService.createObservation( + observationData.token, + observationData.solutionDetails._id, + observation, + userRoleAndProfileInformation && Object.keys(userRoleAndProfileInformation).length > 0 ? userRoleAndProfileInformation : {} + ); + + if ( observationCreated.success ) { + result["observationId"] = observationCreated.data._id; + } + + result["solutionId"] = observationData.solutionDetails._id; + } - ); - - if (!createdAssessment.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: - CONSTANTS.apiResponses.COULD_NOT_CREATE_ASSESSMENT_SOLUTION, - }; - } - result["solutionId"] = createdAssessment.data._id; - } else { - let assignedAssessmentToUser = - await surveyService.createEntityAssessors( - assessmentData.token, - assessmentData.solutionDetails.programId, - assessmentData.solutionDetails._id, - [assessmentData.entityId] - ); - - if (!assignedAssessmentToUser.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: - CONSTANTS.apiResponses.FAILED_TO_ASSIGNED_ASSESSMENT_TO_USER, - }; - } + return resolve({ + success: true, + data: result + }); - let entitiesAddedToSolution = await surveyService.addEntitiesToSolution( - assessmentData.token, - assessmentData.solutionDetails._id, - [assessmentData.entityId.toString()] - ); - - if (!entitiesAddedToSolution.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.FAILED_TO_ADD_ENTITY_TO_SOLUTION, - }; + } catch (error) { + return resolve({ + message: error.message, + success: false, + status: error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status + }); } + }) +} - let solutionUpdated = await surveyService.updateSolution( - assessmentData.token, - { - project: assessmentData.project, - referenceFrom: "project", - }, - assessmentData.solutionDetails.externalId - ); - - if (!solutionUpdated.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.SOLUTION_NOT_UPDATED, - }; - } +/** + * Observation details + * @method + * @name _entitiesMetaInformation + * @param {Object} entitiesData - entities data. + * @returns {Object} - entities metadata. +*/ - result["solutionId"] = assessmentData.solutionDetails._id; - } +function _entitiesMetaInformation(entitiesData) { + return new Promise(async (resolve, reject) => { + let entityInformation = [] + for ( let index = 0; index < entitiesData.length; index++ ) { + let entityHierarchy = await userProfileService.getParentEntities( entitiesData[index]._id ); + entitiesData[index].metaInformation.hierarchy = entityHierarchy; + entitiesData[index].metaInformation._id = entitiesData[index]._id; + entitiesData[index].metaInformation.entityType = entitiesData[index].entityType; + entitiesData[index].metaInformation.registryDetails = entitiesData[index].registryDetails; + entityInformation.push(entitiesData[index].metaInformation) + } - return resolve({ - success: true, - data: result, - }); - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - }); - } - }); + return resolve (entityInformation); + }) } + /** - * Observation details - * @method - * @name _observationDetails - * @param {Object} observationData - Observation data. - * @returns {Object} - */ + * Project Add And Sync Common information. + * @method + * @name _projectData + * @param {Array} data - Req data. + * @returns {Object} Project Add information. +*/ -function _observationDetails( - observationData, - userRoleAndProfileInformation = {} -) { - return new Promise(async (resolve, reject) => { - try { - let result = {}; +function _projectData(data) { + return new Promise(async (resolve, reject) => { + try { - if (observationData.project) { - let templateTasks = await projectTemplateTaskQueries.taskDocuments( - { - externalId: observationData.project.taskId, - }, - ["_id"] - ); + let projectData = {}; + if (data.categories && data.categories.length > 0) { - if (templateTasks.length > 0) { - observationData.project.taskId = templateTasks[0]._id; - } - } + let categories = + await _projectCategories(data.categories); - if (observationData.solutionDetails.isReusable) { - let observationCreatedFromTemplate = - await surveyService.createObservationFromSolutionTemplate( - observationData.token, - observationData.solutionDetails._id, - { - name: - observationData.solutionDetails.name + "-" + UTILS.epochTime(), - description: - observationData.solutionDetails.name + "-" + UTILS.epochTime(), - program: { - _id: observationData.programId, - name: "", - }, - status: CONSTANTS.common.PUBLISHED_STATUS, - entities: [observationData.entityId], - project: observationData.project, - } - ); + if (!categories.success) { + return resolve(categories); + } - if (!observationCreatedFromTemplate.success) { - throw { - status: HTTP_STATUS_CODE["bad_request"].status, - message: CONSTANTS.apiResponses.OBSERVATION_NOT_CREATED, - }; - } + projectData.categories = categories.data; + } - result["solutionId"] = observationCreatedFromTemplate.data._id; - result["observationId"] = - observationCreatedFromTemplate.data.observationId; - } else { - let startDate = new Date(); - let endDate = new Date(); - endDate.setFullYear(endDate.getFullYear() + 1); - - let observation = { - name: observationData.solutionDetails.name, - description: observationData.solutionDetails.name, - status: CONSTANTS.common.PUBLISHED_STATUS, - startDate: startDate, - endDate: endDate, - entities: [observationData.entityId], - project: observationData.project, - }; - - let observationCreated = await surveyService.createObservation( - observationData.token, - observationData.solutionDetails._id, - observation, - userRoleAndProfileInformation && - Object.keys(userRoleAndProfileInformation).length > 0 - ? userRoleAndProfileInformation - : {} - ); - - if (observationCreated.success) { - result["observationId"] = observationCreated.data._id; - } + if (data.startDate) { + projectData["startDate"] = data.startDate; + } - result["solutionId"] = observationData.solutionDetails._id; - } + if (data.endDate) { + projectData["endDate"] = data.endDate; + } - return resolve({ - success: true, - data: result, - }); - } catch (error) { - return resolve({ - message: error.message, - success: false, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - }); - } - }); -} + if (data.learningResources) { + projectData.learningResources = data.learningResources; + } -/** - * Observation details - * @method - * @name _entitiesMetaInformation - * @param {Object} entitiesData - entities data. - * @returns {Object} - entities metadata. - */ + projectData.syncedAt = new Date(); -function _entitiesMetaInformation(entitiesData) { - return new Promise(async (resolve, reject) => { - let entityInformation = []; - for (let index = 0; index < entitiesData.length; index++) { - let entityHierarchy = await userProfileService.getParentEntities( - entitiesData[index]._id - ); - entitiesData[index].metaInformation.hierarchy = entityHierarchy; - entitiesData[index].metaInformation._id = entitiesData[index]._id; - entitiesData[index].metaInformation.entityType = - entitiesData[index].entityType; - entitiesData[index].metaInformation.registryDetails = - entitiesData[index].registryDetails; - entityInformation.push(entitiesData[index].metaInformation); - } + return resolve({ + success: true, + data: projectData + }); - return resolve(entityInformation); - }); + } catch (error) { + return resolve({ + message: error.message, + status: + error.status ? + error.status : HTTP_STATUS_CODE['internal_server_error'].status, + success: false, + data: {} + }); + } + }) } /** - * Project Add And Sync Common information. - * @method - * @name _projectData - * @param {Array} data - Req data. - * @returns {Object} Project Add information. - */ - -function _projectData(data) { - return new Promise(async (resolve, reject) => { - try { - let projectData = {}; - if (data.categories && data.categories.length > 0) { - let categories = await _projectCategories(data.categories); - - if (!categories.success) { - return resolve(categories); - } + * Validate & Update UserProfile in Projects. + * @method + * @name _updateUserProfileBasedOnUserRoleInfo + * @param {Object} userProfile - userProfile data. + * @param {Object} userRoleInformation - userRoleInformation data. + * @returns {Object} updated UserProfile information. +*/ + +function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) { + return new Promise(async (resolve, reject) => { + try { - projectData.categories = categories.data; - } - if (data.startDate) { - projectData["startDate"] = data.startDate; - } + let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles - if (data.endDate) { - projectData["endDate"] = data.endDate; - } + if(userRoleInformation.role) { // Check if userRoleInformation has role value. + let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. - if (data.learningResources) { - projectData.learningResources = data.learningResources; - } + let resetCurrentUserProfileRoles = false; // Flag to reset current userProfile.profileUserTypes i.e. if current role in profile is not at all there in userRoleInformation.roles + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { - projectData.syncedAt = new Date(); + // Loop through current roles in userProfile.profileUserTypes + for (let pointerToCurrentProfileUserTypes = 0; pointerToCurrentProfileUserTypes < userProfile.profileUserTypes.length; pointerToCurrentProfileUserTypes++) { + const currentProfileUserType = userProfile.profileUserTypes[pointerToCurrentProfileUserTypes]; - return resolve({ - success: true, - data: projectData, - }); - } catch (error) { - return resolve({ - message: error.message, - status: error.status - ? error.status - : HTTP_STATUS_CODE["internal_server_error"].status, - success: false, - data: {}, - }); - } - }); -} + if(currentProfileUserType.subType && currentProfileUserType.subType !== null) { // If the role has a subType -/** - * Validate & Update UserProfile in Projects. - * @method - * @name _updateUserProfileBasedOnUserRoleInfo - * @param {Object} userProfile - userProfile data. - * @param {Object} userRoleInformation - userRoleInformation data. - * @returns {Object} updated UserProfile information. - */ + // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!userRoleInformation.role.toUpperCase().includes(currentProfileUserType.subType.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } else { // If the role subType is null or is not there -function _updateUserProfileBasedOnUserRoleInfo( - userProfile, - userRoleInformation -) { - return new Promise(async (resolve, reject) => { - try { - let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles - - if (userRoleInformation.role) { - // Check if userRoleInformation has role value. - let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. - - let resetCurrentUserProfileRoles = false; // Flag to reset current userProfile.profileUserTypes i.e. if current role in profile is not at all there in userRoleInformation.roles - // Check if userProfile.profileUserTypes exists and is an array of length > 0 - if ( - userProfile.profileUserTypes && - Array.isArray(userProfile.profileUserTypes) && - userProfile.profileUserTypes.length > 0 - ) { - // Loop through current roles in userProfile.profileUserTypes - for ( - let pointerToCurrentProfileUserTypes = 0; - pointerToCurrentProfileUserTypes < - userProfile.profileUserTypes.length; - pointerToCurrentProfileUserTypes++ - ) { - const currentProfileUserType = - userProfile.profileUserTypes[pointerToCurrentProfileUserTypes]; + // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. + if(!userRoleInformation.role.toUpperCase().includes(currentProfileUserType.type.toUpperCase())) { + resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes + break; + } + } + } + } + if(resetCurrentUserProfileRoles) { // Reset userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + } - if ( - currentProfileUserType.subType && - currentProfileUserType.subType !== null - ) { - // If the role has a subType - - // Check if subType exists in userRoleInformation role, if not means profile data is old and should be reset. - if ( - !userRoleInformation.role - .toUpperCase() - .includes(currentProfileUserType.subType.toUpperCase()) - ) { - resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes - break; - } - } else { - // If the role subType is null or is not there - - // Check if type exists in userRoleInformation role, if not means profile data is old and should be reset. - if ( - !userRoleInformation.role - .toUpperCase() - .includes(currentProfileUserType.type.toUpperCase()) - ) { - resetCurrentUserProfileRoles = true; // Reset userProfile.profileUserTypes - break; - } + // Loop through each subRole in userRoleInformation + for (let pointerToRolesInUserInformation = 0; pointerToRolesInUserInformation < rolesInUserRoleInformation.length; pointerToRolesInUserInformation++) { + const subRole = rolesInUserRoleInformation[pointerToRolesInUserInformation]; + // Check if userProfile.profileUserTypes exists and is an array of length > 0 + if(userProfile.profileUserTypes && Array.isArray(userProfile.profileUserTypes) && userProfile.profileUserTypes.length >0) { + if(!_.find(userProfile.profileUserTypes, { 'type': subRole.toLowerCase() }) && !_.find(userProfile.profileUserTypes, { 'subType': subRole.toLowerCase() })) { + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + if(subRole.toUpperCase() === "TEACHER") { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } else { // Make a new entry if userProfile.profileUserTypes is empty or does not exist. + updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes + userProfile.profileUserTypes = new Array; + if(subRole.toUpperCase() === "TEACHER") { // If subRole is teacher + userProfile.profileUserTypes.push({ + "subType" : null, + "type" : "teacher" + }) + } else { // If subRole is not teacher + userProfile.profileUserTypes.push({ + "subType" : subRole.toLowerCase(), + "type" : "administrator" + }) + } + } + } } - } - } - if (resetCurrentUserProfileRoles) { - // Reset userProfile.profileUserTypes - userProfile.profileUserTypes = new Array(); - } - // Loop through each subRole in userRoleInformation - for ( - let pointerToRolesInUserInformation = 0; - pointerToRolesInUserInformation < rolesInUserRoleInformation.length; - pointerToRolesInUserInformation++ - ) { - const subRole = - rolesInUserRoleInformation[pointerToRolesInUserInformation]; - // Check if userProfile.profileUserTypes exists and is an array of length > 0 - if ( - userProfile.profileUserTypes && - Array.isArray(userProfile.profileUserTypes) && - userProfile.profileUserTypes.length > 0 - ) { - if ( - !_.find(userProfile.profileUserTypes, { - type: subRole.toLowerCase(), - }) && - !_.find(userProfile.profileUserTypes, { - subType: subRole.toLowerCase(), - }) - ) { - updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes - if (subRole.toUpperCase() === "TEACHER") { - // If subRole is not teacher - userProfile.profileUserTypes.push({ - subType: null, - type: "teacher", - }); - } else { - // If subRole is not teacher - userProfile.profileUserTypes.push({ - subType: subRole.toLowerCase(), - type: "administrator", - }); - } + if(updateUserProfileRoleInformation) { // If profileUserTypes in userProfile was wrong and is updated as per userRoleInformation + userProfile.userRoleMismatchFoundAndUpdated = true; } - } else { - // Make a new entry if userProfile.profileUserTypes is empty or does not exist. - updateUserProfileRoleInformation = true; // Need to update userProfile.profileUserTypes - userProfile.profileUserTypes = new Array(); - if (subRole.toUpperCase() === "TEACHER") { - // If subRole is teacher - userProfile.profileUserTypes.push({ - subType: null, - type: "teacher", - }); - } else { - // If subRole is not teacher - userProfile.profileUserTypes.push({ - subType: subRole.toLowerCase(), - type: "administrator", - }); - } - } - } - } - - if (updateUserProfileRoleInformation) { - // If profileUserTypes in userProfile was wrong and is updated as per userRoleInformation - userProfile.userRoleMismatchFoundAndUpdated = true; - } - // Create location only object from userRoleInformation - let userRoleInformationLocationObject = _.omit(userRoleInformation, [ - "role", - ]); - - // All location keys from userRoleInformation - let userRoleInfomrationLocationKeys = Object.keys( - userRoleInformationLocationObject - ); - - let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values - - // Loop through all location keys. - for ( - let pointerToUserRoleInfromationLocationKeys = 0; - pointerToUserRoleInfromationLocationKeys < - userRoleInfomrationLocationKeys.length; - pointerToUserRoleInfromationLocationKeys++ - ) { - const locationType = - userRoleInfomrationLocationKeys[ - pointerToUserRoleInfromationLocationKeys - ]; // e.g. state, district, school - const locationValue = userRoleInformationLocationObject[locationType]; // Location UUID values or school code. - - // Check if userProfile.userLocations exists and is an array of length > 0 - if ( - userProfile.userLocations && - Array.isArray(userProfile.userLocations) && - userProfile.userLocations.length > 0 - ) { - if (locationType === "school") { - // If location type school exist check if same is there in userProfile.userLocations - if ( - !_.find(userProfile.userLocations, { - type: "school", - code: locationValue, - }) - ) { - updateUserProfileLocationInformation = true; // School does not exist in userProfile.userLocations, update entire userProfile.userLocations - break; + // Create location only object from userRoleInformation + let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); + + // All location keys from userRoleInformation + let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); + + let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values + + // Loop through all location keys. + for (let pointerToUserRoleInfromationLocationKeys = 0; pointerToUserRoleInfromationLocationKeys < userRoleInfomrationLocationKeys.length; pointerToUserRoleInfromationLocationKeys++) { + + const locationType = userRoleInfomrationLocationKeys[pointerToUserRoleInfromationLocationKeys]; // e.g. state, district, school + const locationValue = userRoleInformationLocationObject[locationType]; // Location UUID values or school code. + + // Check if userProfile.userLocations exists and is an array of length > 0 + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + + if(locationType === "school") { // If location type school exist check if same is there in userProfile.userLocations + if(!_.find(userProfile.userLocations, { 'type': "school", 'code': locationValue })) { + updateUserProfileLocationInformation = true; // School does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } else { // Check if location type is there in userProfile.userLocations and has same value as userRoleInformation + if(!_.find(userProfile.userLocations, { 'type': locationType, 'id': locationValue })) { + updateUserProfileLocationInformation = true; // Location does not exist in userProfile.userLocations, update entire userProfile.userLocations + break; + } + } + } else { + updateUserProfileLocationInformation = true; + break; + } } - } else { - // Check if location type is there in userProfile.userLocations and has same value as userRoleInformation - if ( - !_.find(userProfile.userLocations, { - type: locationType, - id: locationValue, - }) - ) { - updateUserProfileLocationInformation = true; // Location does not exist in userProfile.userLocations, update entire userProfile.userLocations - break; + + if(userProfile.userLocations && Array.isArray(userProfile.userLocations) && userProfile.userLocations.length >0) { + if(userProfile.userLocations.length != userRoleInfomrationLocationKeys.length) { + updateUserProfileLocationInformation = true; + } } - } - } else { - updateUserProfileLocationInformation = true; - break; - } - } - if ( - userProfile.userLocations && - Array.isArray(userProfile.userLocations) && - userProfile.userLocations.length > 0 - ) { - if ( - userProfile.userLocations.length != - userRoleInfomrationLocationKeys.length - ) { - updateUserProfileLocationInformation = true; - } - } + // If userProfile.userLocations has to be updated, get all values and set in userProfile. + if(updateUserProfileLocationInformation) { + + //update userLocations in userProfile + let locationIds = []; + let locationCodes = []; + let userLocations = new Array; + + userRoleInfomrationLocationKeys.forEach( requestedDataKey => { + if (UTILS.checkValidUUID(userRoleInformationLocationObject[requestedDataKey])) { + locationIds.push(userRoleInformationLocationObject[requestedDataKey]); + } else { + locationCodes.push(userRoleInformationLocationObject[requestedDataKey]); + } + }) + + //query for fetch location using id + if ( locationIds.length > 0 ) { + let locationQuery = { + "id" : locationIds + } + + let entityData = await userProfileService.locationSearch(locationQuery); + if ( entityData.success ) { + userLocations = entityData.data; + } + } - // If userProfile.userLocations has to be updated, get all values and set in userProfile. - if (updateUserProfileLocationInformation) { - //update userLocations in userProfile - let locationIds = []; - let locationCodes = []; - let userLocations = new Array(); - - userRoleInfomrationLocationKeys.forEach((requestedDataKey) => { - if ( - UTILS.checkValidUUID( - userRoleInformationLocationObject[requestedDataKey] - ) - ) { - locationIds.push( - userRoleInformationLocationObject[requestedDataKey] - ); - } else { - locationCodes.push( - userRoleInformationLocationObject[requestedDataKey] - ); - } - }); + // query for fetch location using code + if ( locationCodes.length > 0 ) { + let codeQuery = { + "code" : locationCodes + } - //query for fetch location using id - if (locationIds.length > 0) { - let locationQuery = { - id: locationIds, - }; - - let entityData = await userProfileService.locationSearch( - locationQuery - ); - if (entityData.success) { - userLocations = entityData.data; - } - } + let entityData = await userProfileService.locationSearch(codeQuery); + if ( entityData.success ) { + userLocations = userLocations.concat(entityData.data); + } + } - // query for fetch location using code - if (locationCodes.length > 0) { - let codeQuery = { - code: locationCodes, - }; + if ( userLocations.length > 0 ) { + userProfile["userLocations"] = userLocations; + userProfile.userLocationsMismatchFoundAndUpdated = true; // If userLocations in userProfile was wrong and is updated as per userRoleInformation + } + } - let entityData = await userProfileService.locationSearch(codeQuery); - if (entityData.success) { - userLocations = userLocations.concat(entityData.data); - } - } + return resolve({ + success: true, + profileMismatchFound : (updateUserProfileLocationInformation || updateUserProfileRoleInformation) ? true : false, + data: userProfile + }); - if (userLocations.length > 0) { - userProfile["userLocations"] = userLocations; - userProfile.userLocationsMismatchFoundAndUpdated = true; // If userLocations in userProfile was wrong and is updated as per userRoleInformation + } catch (error) { + return resolve({ + status: error.status || HTTP_STATUS_CODE['internal_server_error'].status, + message: error.message || HTTP_STATUS_CODE['internal_server_error'].message, + data : false + }); } - } - - return resolve({ - success: true, - profileMismatchFound: - updateUserProfileLocationInformation || - updateUserProfileRoleInformation - ? true - : false, - data: userProfile, - }); - } catch (error) { - return resolve({ - status: - error.status || HTTP_STATUS_CODE["internal_server_error"].status, - message: - error.message || HTTP_STATUS_CODE["internal_server_error"].message, - data: false, - }); - } - }); -} + }) +} \ No newline at end of file diff --git a/release-notes/7.0.0.md b/release-notes/7.0.0.md index 427bb7aa..b23b7838 100644 --- a/release-notes/7.0.0.md +++ b/release-notes/7.0.0.md @@ -26,4 +26,5 @@ In this release, we have introduced four new environment variables. USER_DELETE_TOPIC={{user_delete_topic_name | default("")}} ID={{ml_project_service_id | default("")}} + TELEMETRY_ON_OFF={{telemetry_on_off | default("ON")}} TELEMETRY_TOPIC={{telemetry_raw_topic_name | default("")}} \ No newline at end of file From aaf7bb4fdf3599e986b0377961ca0cbea0909ee4 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 20 Nov 2023 17:36:23 +0530 Subject: [PATCH 334/373] Updated PR --- controllers/v1/userProjects.js | 875 ++++++++++++------------ generics/kafka/consumers/submissions.js | 44 +- generics/middleware/authenticator.js | 161 ++--- 3 files changed, 519 insertions(+), 561 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index dbd26116..052a4f9b 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -6,36 +6,37 @@ */ // Dependencies -const csv = require("csvtojson"); +const csv = require('csvtojson'); const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); -/** - * UserProjects - * @class - */ + /** + * UserProjects + * @class +*/ module.exports = class UserProjects extends Abstract { - /** - * @apiDefine errorBody - * @apiError {String} status 4XX,5XX - * @apiError {String} message Error - */ - /** - * @apiDefine successBody - * @apiSuccess {String} status 200 - * @apiSuccess {String} result Data - */ + /** + * @apiDefine errorBody + * @apiError {String} status 4XX,5XX + * @apiError {String} message Error + */ - constructor() { - super("projects"); - } + /** + * @apiDefine successBody + * @apiSuccess {String} status 200 + * @apiSuccess {String} result Data + */ + + constructor() { + super("projects"); + } - static get name() { - return "userProjects"; - } + static get name() { + return "userProjects"; + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/sync/:projectId?lastDownloadedAt=:epochTime * Sync project. * @apiVersion 1.0.0 @@ -113,51 +114,47 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Sync projects. - * @method - * @name sync - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @returns {JSON} Create Self projects. - */ + /** + * Sync projects. + * @method + * @name sync + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @returns {JSON} Create Self projects. + */ - async sync(req) { - return new Promise(async (resolve, reject) => { - try { - let createdProject = await userProjectsHelper.sync( - req.params._id, - req.query.lastDownloadedAt, - req.body, - req.userDetails.userInformation.userId, - req.userDetails.userToken, - req.headers["x-app-id"] - ? req.headers["x-app-id"] - : req.headers.appname - ? req.headers.appname - : "", - req.headers["x-app-ver"] - ? req.headers["x-app-ver"] - : req.headers.appversion - ? req.headers.appversion - : "" - ); - - createdProject.result = createdProject.data; - - return resolve(createdProject); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + async sync(req) { + return new Promise(async (resolve, reject) => { + try { + let createdProject = await userProjectsHelper.sync( + req.params._id, + req.query.lastDownloadedAt, + req.body, + req.userDetails.userInformation.userId, + req.userDetails.userToken, + req.headers["x-app-id"] ? + req.headers["x-app-id"] : + req.headers.appname ? req.headers.appname : "", + req.headers["x-app-ver"] ? + req.headers["x-app-ver"] : + req.headers.appversion ? req.headers.appversion : "" + ); - /** + createdProject.result = createdProject.data; + + return resolve(createdProject); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {post} /improvement-project/api/v1/userProjects/details/:projectId?programId=:programId&solutionId=:solutionId&templateId=:templateId * Project Details. * @apiVersion 2.0.0 @@ -249,52 +246,50 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Project details - * @method - * @name details - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @returns {JSON} Create Self projects. - */ + /** + * Project details + * @method + * @name details + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @returns {JSON} Create Self projects. + */ - async details(req) { - return new Promise(async (resolve, reject) => { - try { - let projectDetails = await userProjectsHelper.detailsV2( - req.params._id ? req.params._id : "", - req.query.solutionId, - req.userDetails.userInformation.userId, - req.userDetails.userToken, - req.body, - req.headers["x-app-id"] - ? req.headers["x-app-id"] - : req.headers.appname - ? req.headers.appname - : "", - req.headers["x-app-ver"] - ? req.headers["x-app-ver"] - : req.headers.appversion - ? req.headers.appversion - : "", - req.query.templateId - ); - - projectDetails.result = projectDetails.data; - - return resolve(projectDetails); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + async details(req) { + return new Promise(async (resolve, reject) => { + try { - /** + let projectDetails = + await userProjectsHelper.detailsV2( + req.params._id ? req.params._id : "", + req.query.solutionId, + req.userDetails.userInformation.userId, + req.userDetails.userToken, + req.body, + req.headers["x-app-id"] ? + req.headers["x-app-id"] : + req.headers.appname ? req.headers.appname : "", + req.headers["x-app-ver"] ? + req.headers["x-app-ver"] : + req.headers.appversion ? req.headers.appversion : "", + req.query.templateId + ); + + projectDetails.result = projectDetails.data; + + return resolve(projectDetails); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {post} /improvement-project/api/v1/userProjects/tasksStatus/:projectId * User Project tasks status * @apiVersion 1.0.0 @@ -329,38 +324,39 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Tasks status - * @method - * @name tasksStatus - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @returns {JSON} status of tasks - */ + /** + * Tasks status + * @method + * @name tasksStatus + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @returns {JSON} status of tasks + */ + + async tasksStatus(req) { + return new Promise(async (resolve, reject) => { + try { - async tasksStatus(req) { - return new Promise(async (resolve, reject) => { - try { - let taskStatus = await userProjectsHelper.tasksStatus( - req.params._id, - req.body.taskIds - ); - - taskStatus.result = taskStatus.data; - - return resolve(taskStatus); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + let taskStatus = await userProjectsHelper.tasksStatus( + req.params._id, + req.body.taskIds + ); - /** + taskStatus.result = taskStatus.data; + + return resolve(taskStatus); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {post} /improvement-project/api/v1/userProjects/solutionDetails/:projectId?taskId=:taskId * User project solution details * @apiVersion 1.0.0 @@ -402,41 +398,42 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Solutions details information. - * @method - * @name status - * @param {Object} req - request data. - * @param {String} req.params._id - Project id. - * @param {String} req.query.taskId - task id. - * @returns {JSON} Solutions details - */ + /** + * Solutions details information. + * @method + * @name status + * @param {Object} req - request data. + * @param {String} req.params._id - Project id. + * @param {String} req.query.taskId - task id. + * @returns {JSON} Solutions details + */ + + async solutionDetails(req) { + return new Promise(async (resolve, reject) => { + try { - async solutionDetails(req) { - return new Promise(async (resolve, reject) => { - try { - let solutionDetails = await userProjectsHelper.solutionDetails( - req.userDetails.userToken, - req.params._id, - req.query.taskId, - req.body - ); - - solutionDetails.result = solutionDetails.data; - - return resolve(solutionDetails); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + let solutionDetails = await userProjectsHelper.solutionDetails( + req.userDetails.userToken, + req.params._id, + req.query.taskId, + req.body + ); - /** + solutionDetails.result = solutionDetails.data; + + return resolve(solutionDetails); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {post} /improvement-project/api/v1/userProjects/add * Add project. * @apiVersion 1.0.0 @@ -512,48 +509,45 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Add projects. - * @method - * @name add - * @param {Object} req - request data. - * @returns {JSON} Create Self projects. - */ + /** + * Add projects. + * @method + * @name add + * @param {Object} req - request data. + * @returns {JSON} Create Self projects. + */ - async add(req) { - return new Promise(async (resolve, reject) => { - try { - let createdProject = await userProjectsHelper.add( - req.body, - req.userDetails.userInformation.userId, - req.userDetails.userToken, - req.headers["x-app-id"] - ? req.headers["x-app-id"] - : req.headers.appname - ? req.headers.appname - : "", - req.headers["x-app-ver"] - ? req.headers["x-app-ver"] - : req.headers.appversion - ? req.headers.appversion - : "" - ); - - createdProject.result = createdProject.data; - - return resolve(createdProject); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + async add(req) { + return new Promise(async (resolve, reject) => { + try { - /** + let createdProject = await userProjectsHelper.add( + req.body, + req.userDetails.userInformation.userId, + req.userDetails.userToken, + req.headers["x-app-id"] ? + req.headers["x-app-id"] : + req.headers.appname ? req.headers.appname : "", + req.headers["x-app-ver"] ? + req.headers["x-app-ver"] : + req.headers.appversion ? req.headers.appversion : "" + ); + + createdProject.result = createdProject.data; + + return resolve(createdProject); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {get} /improvement-project/api/v1/userProjects/userAssigned?page=:page&limit=:limit&search=:search&filter=:assignedToMe * List of user assigned project. * @apiVersion 1.0.0 @@ -585,88 +579,89 @@ module.exports = class UserProjects extends Abstract { * @param {Object} req - request data. * @returns {JSON} List of user assigned projects. */ + + async userAssigned(req) { + return new Promise(async (resolve, reject) => { + try { - async userAssigned(req) { - return new Promise(async (resolve, reject) => { - try { - let projects = await userProjectsHelper.userAssigned( - req.userDetails.userInformation.userId, - req.pageSize, - req.pageNo, - req.searchText, - req.query.filter - ); - - projects.result = projects.data; - - return resolve(projects); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + let projects = await userProjectsHelper.userAssigned( + req.userDetails.userInformation.userId, + req.pageSize, + req.pageNo, + req.searchText, + req.query.filter + ); - /** - * @api {get} /improvement-project/api/v1/userProjects/share/:projectId?tasks=:taskId1,:taskId2 - * Share project and task pdf report. - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/share/6065ced7e9259b7f0b1f5d66?tasks=4d074de7-7059-4d99-9da9-452b0d32e081 - * @apiParamExample {json} Response: - * { - * "message": "Report generated succesfully", - * "status": 200, - * "result" : { - * "data" : { - * "downloadUrl": "http://localhost:4700/dhiti/api/v1/observations/pdfReportsUrl?id=dG1wLzVhNzZjMTY5LTA5YjAtNGU3Zi04ZmNhLTg0NDc5ZmI2YTNiNC0tODUyOA==" - * } - * } - * } - * @apiUse successBody - * @apiUse errorBody - */ + projects.result = projects.data; + + return resolve(projects); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } - /* - * Share project and task pdf report. - * @method - * @name share - * @param {Object} req - request data. - * @param {String} req.params._id - projectId - * @returns {JSON} Downloadable pdf url. - */ + /** + * @api {get} /improvement-project/api/v1/userProjects/share/:projectId?tasks=:taskId1,:taskId2 + * Share project and task pdf report. + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/share/6065ced7e9259b7f0b1f5d66?tasks=4d074de7-7059-4d99-9da9-452b0d32e081 + * @apiParamExample {json} Response: + * { + * "message": "Report generated succesfully", + * "status": 200, + * "result" : { + * "data" : { + * "downloadUrl": "http://localhost:4700/dhiti/api/v1/observations/pdfReportsUrl?id=dG1wLzVhNzZjMTY5LTA5YjAtNGU3Zi04ZmNhLTg0NDc5ZmI2YTNiNC0tODUyOA==" + * } + * } + * } + * @apiUse successBody + * @apiUse errorBody + */ - async share(req) { - return new Promise(async (resolve, reject) => { - try { - let taskIds = req.query.tasks ? req.query.tasks.split(",") : []; - - let report = await userProjectsHelper.share( - req.params._id, - taskIds, - req.userDetails.userToken, - req.headers["x-app-ver"] - ); - return resolve({ - message: report.message, - result: report.data, - }); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + /* + * Share project and task pdf report. + * @method + * @name share + * @param {Object} req - request data. + * @param {String} req.params._id - projectId + * @returns {JSON} Downloadable pdf url. + */ - /** + async share(req) { + return new Promise(async (resolve, reject) => { + try { + + let taskIds = req.query.tasks ? req.query.tasks.split(",") : []; + + let report = await userProjectsHelper.share( + req.params._id, + taskIds, + req.userDetails.userToken, + req.headers['x-app-ver'] + ); + return resolve({ + message: report.message, + result: report.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {get} /improvement-project/api/v1/userProjects/importedProjects/:programId * @apiVersion 1.0.0 * @apiGroup Lists of User Imported Projects @@ -699,36 +694,37 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /* - * List of user imported projects - * @method - * @name importedProjects - * @returns {JSON} List of imported projects. - */ + /* + * List of user imported projects + * @method + * @name importedProjects + * @returns {JSON} List of imported projects. + */ - async importedProjects(req) { - return new Promise(async (resolve, reject) => { - try { - let importedProjects = await userProjectsHelper.importedProjects( - req.userDetails.userInformation.userId, - req.params._id ? req.params._id : "" - ); - - importedProjects["result"] = importedProjects["data"]; - - return resolve(importedProjects); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + async importedProjects(req) { + return new Promise(async (resolve, reject) => { + try { - /** + let importedProjects = await userProjectsHelper.importedProjects( + req.userDetails.userInformation.userId, + req.params._id ? req.params._id : "" + ); + + importedProjects["result"] = importedProjects["data"]; + + return resolve(importedProjects); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {post} /improvement-project/api/v1/userProjects/list * Lists of projects. * @apiVersion 0.0.1 @@ -762,25 +758,26 @@ module.exports = class UserProjects extends Abstract { * @method * @name list * @returns {JSON} List projects. - */ + */ - async list(req) { - return new Promise(async (resolve, reject) => { - try { - let projects = await userProjectsHelper.list(req.body); - return resolve(projects); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + async list(req) { + return new Promise(async (resolve, reject) => { + try { - /** + let projects = await userProjectsHelper.list(req.body); + return resolve(projects); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }); + } + + /** * @api {post} /improvement-project/api/v1/userProjects/importFromLibrary/:projectTemplateId&isATargetedSolution=false * Import project from library. * @apiVersion 1.0.0 @@ -922,43 +919,44 @@ module.exports = class UserProjects extends Abstract { * @apiUse errorBody */ - /** - * Import project from library. - * @method - * @name importFromLibrary - * @param {Object} req - request data. - * @param {String} req.params._id - project Template Id. - * @returns {JSON} import project from library. - */ + /** + * Import project from library. + * @method + * @name importFromLibrary + * @param {Object} req - request data. + * @param {String} req.params._id - project Template Id. + * @returns {JSON} import project from library. + */ - async importFromLibrary(req) { - return new Promise(async (resolve, reject) => { - try { - const createdProject = await userProjectsHelper.importFromLibrary( - req.params._id, - req.body, - req.userDetails.userToken, - req.userDetails.userInformation.userId, - req.query.isATargetedSolution ? req.query.isATargetedSolution : "" - ); - - return resolve({ - status: createdProject.status, - message: createdProject.message, - result: createdProject.data, - }); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + async importFromLibrary(req) { + return new Promise(async (resolve, reject) => { + try { + + const createdProject = await userProjectsHelper.importFromLibrary( + req.params._id, + req.body, + req.userDetails.userToken, + req.userDetails.userInformation.userId, + req.query.isATargetedSolution ? req.query.isATargetedSolution : "" + ); - /** + return resolve({ + status: createdProject.status, + message: createdProject.message, + result: createdProject.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + + /** * @api {post} /improvement-project/api/v1/userProjects/certificateCallback * Project certificate callback * @apiVersion 1.0.0 @@ -996,34 +994,27 @@ module.exports = class UserProjects extends Abstract { * @returns {JSON} certificate details. */ - async certificateCallback(req) { + async certificateCallback(req) { return new Promise(async (resolve, reject) => { - try { - //console request body to check if callback is coming or not and to check any structural change is there or not - console.log( - "-------------callback request body------------", - JSON.stringify(req.body) - ); - let certificateDetails = await userProjectsHelper.certificateCallback( - req.body.data.transactionId, - req.body.data.osid - ); - return resolve({ - message: certificateDetails.message, - result: certificateDetails.data, - }); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + try { + //console request body to check if callback is coming or not and to check any structural change is there or not + console.log("-------------callback request body------------",JSON.stringify(req.body)) + let certificateDetails = await userProjectsHelper.certificateCallback( req.body.data.transactionId, req.body.data.osid ); + return resolve({ + message: certificateDetails.message, + result: certificateDetails.data + }); + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } - /** + /** * @api {get} /improvement-project/api/v1/userProjects/certificates * List of user project with certificate * @apiVersion 1.0.0 @@ -1070,29 +1061,27 @@ module.exports = class UserProjects extends Abstract { * @returns {JSON} User project detaills with certificate */ - async certificates(req) { - return new Promise(async (resolve, reject) => { - try { - // fetch projects data of user, whish has certificate on completion - let projectDetails = await userProjectsHelper.certificates( - req.userDetails.userInformation.userId - ); - return resolve({ - message: projectDetails.message, - result: projectDetails.data, - }); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } + async certificates(req) { + return new Promise(async (resolve, reject) => { + try { + // fetch projects data of user, whish has certificate on completion + let projectDetails = await userProjectsHelper.certificates( req.userDetails.userInformation.userId ); + return resolve({ + message: projectDetails.message, + result: projectDetails.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } - /** + /** * @api {post} /improvement-project/api/v1/userProjects/certificateReIssue * ReIssue project certificate (admin api) * @apiVersion 1.0.0 @@ -1113,30 +1102,28 @@ module.exports = class UserProjects extends Abstract { * @returns {JSON} Reissued details */ - async certificateReIssue(req) { - return new Promise(async (resolve, reject) => { - try { - // ReIssue certificate of given project : projectId is passed as param - // This console has to be removed- adding to check the Issuer kid value in case rancher doesn't display console while deployment - console.log( - "+++++CERTIFICATE_ISSUER_KID+++++ : ", - CERTIFICATE_ISSUER_KID - ); - let projectDetails = await userProjectsHelper.certificateReIssue( - req.params._id - ); - return resolve({ - message: projectDetails.message, - result: projectDetails.data, - }); - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: - error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error, - }); - } - }); - } -}; + async certificateReIssue(req) { + return new Promise(async (resolve, reject) => { + try { + // ReIssue certificate of given project : projectId is passed as param + // This console has to be removed- adding to check the Issuer kid value in case rancher doesn't display console while deployment + console.log("+++++CERTIFICATE_ISSUER_KID+++++ : ",CERTIFICATE_ISSUER_KID) + let projectDetails = await userProjectsHelper.certificateReIssue( + req.params._id, + ); + return resolve({ + message: projectDetails.message, + result: projectDetails.data + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + +}; \ No newline at end of file diff --git a/generics/kafka/consumers/submissions.js b/generics/kafka/consumers/submissions.js index 9ac9a300..e2411f53 100644 --- a/generics/kafka/consumers/submissions.js +++ b/generics/kafka/consumers/submissions.js @@ -10,24 +10,26 @@ const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); /** - * submission consumer message received. - * @function - * @name messageReceived - * @param {String} message - consumer data - * @returns {Promise} return a Promise. - */ + * submission consumer message received. + * @function + * @name messageReceived + * @param {String} message - consumer data + * @returns {Promise} return a Promise. +*/ + var messageReceived = function (message) { + return new Promise(async function (resolve, reject) { + try { + let parsedMessage = JSON.parse(message.value); - + let submissionDocument = { - _id: parsedMessage._id.toString(), - status: parsedMessage.status, - completedDate: parsedMessage.submissionDate - ? parsedMessage.submissionDate - : "", + "_id" : parsedMessage._id.toString(), + "status" : parsedMessage.status, + "completedDate" : parsedMessage.submissionDate ? parsedMessage.submissionDate : "" }; await userProjectsHelper.pushSubmissionToTask( @@ -40,28 +42,32 @@ var messageReceived = function (message) { } catch (error) { return reject(error); } + }); }; /** - * If message is not received. - * @function - * @name errorTriggered - * @param {Object} error - error object - * @returns {Promise} return a Promise. - */ + * If message is not received. + * @function + * @name errorTriggered + * @param {Object} error - error object + * @returns {Promise} return a Promise. +*/ var errorTriggered = function (error) { + return new Promise(function (resolve, reject) { + try { return resolve(error); } catch (error) { return reject(error); } + }); }; module.exports = { messageReceived: messageReceived, - errorTriggered: errorTriggered, + errorTriggered: errorTriggered }; diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index 32c4b20f..b34628ab 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -6,13 +6,9 @@ */ // dependencies -const jwt = require("jsonwebtoken"); -const fs = require("fs"); -const keyCloakPublicKeyPath = - process.env.KEYCLOAK_PUBLIC_KEY_PATH && - process.env.KEYCLOAK_PUBLIC_KEY_PATH != "" - ? PROJECT_ROOT_DIRECTORY + "/" + process.env.KEYCLOAK_PUBLIC_KEY_PATH + "/" - : PROJECT_ROOT_DIRECTORY + "/" + "keycloak-public-keys/"; +const jwt = require('jsonwebtoken'); +const fs = require('fs'); +const keyCloakPublicKeyPath = (process.env.KEYCLOAK_PUBLIC_KEY_PATH && process.env.KEYCLOAK_PUBLIC_KEY_PATH != "") ? PROJECT_ROOT_DIRECTORY+"/"+process.env.KEYCLOAK_PUBLIC_KEY_PATH+"/" : PROJECT_ROOT_DIRECTORY+"/"+"keycloak-public-keys/" ; const PEM_FILE_BEGIN_STRING = "-----BEGIN PUBLIC KEY-----"; const PEM_FILE_END_STRING = "-----END PUBLIC KEY-----"; @@ -20,7 +16,7 @@ var respUtil = function (resp) { return { status: resp.errCode, message: resp.errMsg, - currentDate: new Date().toISOString(), + currentDate: new Date().toISOString() }; }; @@ -37,12 +33,11 @@ var removedHeaders = [ "dnt", "postman-token", "cache-control", - "connection", + "connection" ]; module.exports = async function (req, res, next, token = "") { - next(); - return; + removedHeaders.forEach(function (e) { delete req.headers[e]; }); @@ -51,60 +46,48 @@ module.exports = async function (req, res, next, token = "") { if (!req.rspObj) req.rspObj = {}; var rspObj = req.rspObj; + // Allow search endpoints for non-logged in users. let guestAccess = false; - let guestAccessPaths = [ - "/dataPipeline/", - "/templates/details", - "userProjects/certificateCallback", - ]; - await Promise.all( - guestAccessPaths.map(async function (path) { - if (req.path.includes(path)) { - guestAccess = true; - } - }) - ); - - if (guestAccess == true && !token) { + let guestAccessPaths = ["/dataPipeline/","/templates/details","userProjects/certificateCallback"]; + await Promise.all(guestAccessPaths.map(async function (path) { + if (req.path.includes(path)) { + guestAccess = true; + } + })); + + if( guestAccess == true && !token ) { next(); return; } let internalAccessApiPaths = ["/templates/bulkCreate"]; let performInternalAccessTokenCheck = false; - await Promise.all( - internalAccessApiPaths.map(async function (path) { - if (req.path.includes(path)) { - performInternalAccessTokenCheck = true; - } - }) - ); + await Promise.all(internalAccessApiPaths.map(async function (path) { + if (req.path.includes(path)) { + performInternalAccessTokenCheck = true; + } + })); if (performInternalAccessTokenCheck) { - if ( - req.headers["internal-access-token"] !== process.env.INTERNAL_ACCESS_TOKEN - ) { + if (req.headers["internal-access-token"] !== process.env.INTERNAL_ACCESS_TOKEN) { rspObj.errCode = CONSTANTS.apiResponses.TOKEN_MISSING_CODE; rspObj.errMsg = CONSTANTS.apiResponses.TOKEN_MISSING_MESSAGE; - rspObj.responseCode = HTTP_STATUS_CODE["unauthorized"].status; - return res - .status(HTTP_STATUS_CODE["unauthorized"].status) - .send(respUtil(rspObj)); + rspObj.responseCode = HTTP_STATUS_CODE['unauthorized'].status; + return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } - if (!token) { + if(!token){ next(); return; } } + if (!token) { rspObj.errCode = CONSTANTS.apiResponses.TOKEN_MISSING_CODE; rspObj.errMsg = CONSTANTS.apiResponses.TOKEN_MISSING_MESSAGE; rspObj.responseCode = HTTP_STATUS_CODE["unauthorized"].status; - return res - .status(HTTP_STATUS_CODE["unauthorized"].status) - .send(respUtil(rspObj)); + return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } rspObj.errCode = CONSTANTS.apiResponses.TOKEN_INVALID_CODE; @@ -112,73 +95,55 @@ module.exports = async function (req, res, next, token = "") { rspObj.responseCode = HTTP_STATUS_CODE["unauthorized"].status; var decoded = jwt.decode(token, { complete: true }); - if (decoded === null || decoded.header === undefined) { - return res - .status(HTTP_STATUS_CODE["unauthorized"].status) - .send(respUtil(rspObj)); + if(decoded === null || decoded.header === undefined){ + return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } - const kid = decoded.header.kid; + const kid = decoded.header.kid let cert = ""; let path = keyCloakPublicKeyPath + kid; - + if (fs.existsSync(path)) { - let accessKeyFile = await fs.readFileSync(path); - - if (accessKeyFile) { - if (!accessKeyFile.includes(PEM_FILE_BEGIN_STRING)) { - cert = - PEM_FILE_BEGIN_STRING + - "\n" + - accessKeyFile + - "\n" + - PEM_FILE_END_STRING; - } else { + + let accessKeyFile = await fs.readFileSync(path); + + if(accessKeyFile) { + if(!accessKeyFile.includes(PEM_FILE_BEGIN_STRING)){ + cert = PEM_FILE_BEGIN_STRING+"\n"+accessKeyFile+"\n"+PEM_FILE_END_STRING; + }else { cert = fs.readFileSync(path); - } + } } + + jwt.verify(token, cert, { algorithm: ['sha1', 'RS256', 'HS256'] }, function (err, decode) { - jwt.verify( - token, - cert, - { algorithm: ["sha1", "RS256", "HS256"] }, - function (err, decode) { - if (err) { - return res - .status(HTTP_STATUS_CODE["unauthorized"].status) - .send(respUtil(rspObj)); + if (err) { + return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); + } + + if (decode !== undefined) { + const expiry = decode.exp; + const now = new Date(); + if (now.getTime() > expiry * 1000) { + return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } - if (decode !== undefined) { - const expiry = decode.exp; - const now = new Date(); - if (now.getTime() > expiry * 1000) { - return res - .status(HTTP_STATUS_CODE["unauthorized"].status) - .send(respUtil(rspObj)); + req.userDetails = { + userToken : token, + userInformation : { + userId : decode.sub.split(":").pop(), + userName : decode.preferred_username, + email : decode.email, + firstName : decode.name } + }; - req.userDetails = { - userToken: token, - userInformation: { - userId: decode.sub.split(":").pop(), - userName: decode.preferred_username, - email: decode.email, - firstName: decode.name, - }, - }; - - next(); - } else { - return res - .status(HTTP_STATUS_CODE["unauthorized"].status) - .send(respUtil(rspObj)); - } + next(); + } else { + return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } - ); + }); } else { - return res - .status(HTTP_STATUS_CODE["unauthorized"].status) - .send(respUtil(rspObj)); + return res.status(HTTP_STATUS_CODE["unauthorized"].status).send(respUtil(rspObj)); } -}; +}; \ No newline at end of file From 61b7839def3cde21017a4ffa76b0d2ef605470bd Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Nov 2023 10:51:51 +0530 Subject: [PATCH 335/373] Added ON of status for user delete --- .gitignore | 4 +- config/kafka.js | 90 +++++++++++++++++++------------------ databaseQueries/projects.js | 6 +-- envVariables.js | 9 +++- 4 files changed, 60 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index 90cf764a..588ab0e1 100644 --- a/.gitignore +++ b/.gitignore @@ -69,4 +69,6 @@ config/credentials/* *.DS_Store package-lock.json -keycloak-public-keys/ \ No newline at end of file +keycloak-public-keys/ + +.dcignore \ No newline at end of file diff --git a/config/kafka.js b/config/kafka.js index 57951514..9bd2f6a5 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -11,6 +11,7 @@ const kafka = require('kafka-node'); const SUBMISSION_TOPIC = process.env.SUBMISSION_TOPIC; const CERTIFICATE_TOPIC = process.env.PROJECT_SUBMISSION_TOPIC; const USER_DELETE_TOPIC = process.env.USER_DELETE_TOPIC; +const USER_DELETE_ON_OFF = process.env.USER_DELETE_ON_OFF /** * Kafka configurations. * @function @@ -52,7 +53,7 @@ const connect = function() { ); // user Delete Consumer - _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL); + _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL, USER_DELETE_ON_OFF); return { kafkaProducer: producer, @@ -69,57 +70,60 @@ const connect = function() { * @param {String} host - kafka host */ -var _sendToKafkaConsumers = function (topic,host) { - - if (topic && topic != "") { - - let consumer = new kafka.ConsumerGroup( - { - kafkaHost : host, - groupId : process.env.KAFKA_GROUP_ID, - autoCommit : true - },topic - ); - - consumer.on('message', async function (message) { - - console.log("-------Kafka consumer log starts here------------------"); - console.log("Topic Name: ", topic); - console.log("Message: ", JSON.stringify(message)); - console.log("-------Kafka consumer log ends here------------------"); - +var _sendToKafkaConsumers = function (topic,host, status="ON") { + if(status !== "OFF"){ + + if (topic && topic != "") { + + let consumer = new kafka.ConsumerGroup( + { + kafkaHost : host, + groupId : process.env.KAFKA_GROUP_ID, + autoCommit : true + },topic + ); + + consumer.on('message', async function (message) { + + console.log("-------Kafka consumer log starts here------------------"); + console.log("Topic Name: ", topic); + console.log("Message: ", JSON.stringify(message)); + console.log("-------Kafka consumer log ends here------------------"); + - if (message && message.topic === SUBMISSION_TOPIC) { - submissionsConsumer.messageReceived(message); - } - // call projectCertificateConsumer - if (message && message.topic === CERTIFICATE_TOPIC) { - projectCertificateConsumer.messageReceived(message); - } + if (message && message.topic === SUBMISSION_TOPIC) { + submissionsConsumer.messageReceived(message); + } + // call projectCertificateConsumer + if (message && message.topic === CERTIFICATE_TOPIC) { + projectCertificateConsumer.messageReceived(message); + } - // call userDelete consumer - if (message && message.topic === USER_DELETE_TOPIC) { - userDeleteConsumer.messageReceived(message); - } + // call userDelete consumer + if (message && message.topic === USER_DELETE_TOPIC) { + userDeleteConsumer.messageReceived(message); + } - }); + }); - consumer.on('error', async function (error) { + consumer.on('error', async function (error) { - if(error.topics && error.topics[0] === SUBMISSION_TOPIC) { - submissionsConsumer.errorTriggered(error); - } - if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { - projectCertificateConsumer.errorTriggered(error); - } + if(error.topics && error.topics[0] === SUBMISSION_TOPIC) { + submissionsConsumer.errorTriggered(error); + } + if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { + projectCertificateConsumer.errorTriggered(error); + } - if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { - userDeleteConsumer.errorTriggered(error); - } + if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { + userDeleteConsumer.errorTriggered(error); + } - }); + }); + } } + }; module.exports = connect; diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 2329bd93..3e7e6236 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -141,13 +141,13 @@ module.exports = class Projects { return new Promise(async (resolve, reject) => { try { - let projectsData = await database.models.projects.updateMany( + let updatedProjectCount = await database.models.projects.updateMany( query, update, options ); - if( projectsData) { - return resolve(projectsData); + if( updatedProjectCount) { + return resolve(updatedProjectCount); } } catch (error) { return reject(error); diff --git a/envVariables.js b/envVariables.js index 61e64153..71402ce3 100644 --- a/envVariables.js +++ b/envVariables.js @@ -61,9 +61,14 @@ "optional" : false, "default" : "ON" }, + "USER_DELETE_ON_OFF": { + message: "Enable/Disable user delete flow", + optional: false, + default : "ON" + }, "USER_DELETE_TOPIC": { message: "Required user delete kafka consumer topic name", - optional: false, + optional: true, }, "ID": { message: "Required Service ID", @@ -75,7 +80,7 @@ }, "TELEMETRY_TOPIC": { message: "Required telemetry topic", - optional: false, + optional: true, }, } From 0ed9833d67101f8736e72cdff574cc5158ba0a86 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Nov 2023 10:53:35 +0530 Subject: [PATCH 336/373] Added ON of status for user delete --- .env.sample | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env.sample b/.env.sample index f92108d3..02ed9847 100644 --- a/.env.sample +++ b/.env.sample @@ -42,6 +42,8 @@ PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" USER_DELETE_TOPIC = {{env_name}}.delete.user // Topic name for user delete event consumer +USER_DELETE_ON_OFF = ON/OFF // enable/disable user delete flow + ID = ID = {{env_name}}.{{sunbird_instance}}.ml.core.service // ID of service TELEMETRY_ON_OFF = ON/OFF // telemetry service on off From d484d1759467a350cd65aca6b1c45d373ff9d5cf Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Nov 2023 10:59:45 +0530 Subject: [PATCH 337/373] Added ON of status for user delete --- .env.sample | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.sample b/.env.sample index 02ed9847..42893888 100644 --- a/.env.sample +++ b/.env.sample @@ -40,10 +40,10 @@ CERTIFICATE_SERVICE_URL = http://registry-service:8081 PROJECT_CERTIFICATE_ON_OFF = "ON/OFF" // Project certificate enable or disable flag -USER_DELETE_TOPIC = {{env_name}}.delete.user // Topic name for user delete event consumer - USER_DELETE_ON_OFF = ON/OFF // enable/disable user delete flow +USER_DELETE_TOPIC = {{env_name}}.delete.user // Topic name for user delete event consumer + ID = ID = {{env_name}}.{{sunbird_instance}}.ml.core.service // ID of service TELEMETRY_ON_OFF = ON/OFF // telemetry service on off From 91a4ebf261b0dd07ca3c2ee772e2f0bf174b886a Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 23 Nov 2023 11:58:46 +0530 Subject: [PATCH 338/373] Added ON of status for user delete --- envVariables.js | 1 + module/userProjects/helper.js | 1 + 2 files changed, 2 insertions(+) diff --git a/envVariables.js b/envVariables.js index 71402ce3..427074f4 100644 --- a/envVariables.js +++ b/envVariables.js @@ -77,6 +77,7 @@ "TELEMETRY_ON_OFF":{ message: "Required telemetry on/off status", optional: false, + default: "ON" }, "TELEMETRY_TOPIC": { message: "Required telemetry topic", diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 89c4b340..463c596c 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -112,6 +112,7 @@ module.exports = class UserProjectsHelper { "userProfile.prevUsedPhone": 1, "userProfile.prevUsedEmail": 1, "userProfile.recoveryPhone": 1, + "userProfile.dob": 1 }, }; let deleteUserPIIDataResult = await projectQueries.updateMany(filter, updateProfile) From 774d28c6eff3eea7493f210b83fbcaea2d9332e6 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 27 Nov 2023 08:56:31 +0530 Subject: [PATCH 339/373] Resolved Comments --- config/kafka.js | 93 ++++++++++++++++++++++++------------------------- envVariables.js | 10 ++++++ 2 files changed, 56 insertions(+), 47 deletions(-) diff --git a/config/kafka.js b/config/kafka.js index 9bd2f6a5..e2633c96 100644 --- a/config/kafka.js +++ b/config/kafka.js @@ -53,7 +53,9 @@ const connect = function() { ); // user Delete Consumer - _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL, USER_DELETE_ON_OFF); + if(USER_DELETE_ON_OFF !== "OFF") { + _sendToKafkaConsumers(USER_DELETE_TOPIC, process.env.KAFKA_URL); + } return { kafkaProducer: producer, @@ -70,60 +72,57 @@ const connect = function() { * @param {String} host - kafka host */ -var _sendToKafkaConsumers = function (topic,host, status="ON") { - if(status !== "OFF"){ - - if (topic && topic != "") { - - let consumer = new kafka.ConsumerGroup( - { - kafkaHost : host, - groupId : process.env.KAFKA_GROUP_ID, - autoCommit : true - },topic - ); - - consumer.on('message', async function (message) { - - console.log("-------Kafka consumer log starts here------------------"); - console.log("Topic Name: ", topic); - console.log("Message: ", JSON.stringify(message)); - console.log("-------Kafka consumer log ends here------------------"); +var _sendToKafkaConsumers = function (topic,host) { + if (topic && topic != "") { + + let consumer = new kafka.ConsumerGroup( + { + kafkaHost : host, + groupId : process.env.KAFKA_GROUP_ID, + autoCommit : true + },topic + ); + + consumer.on('message', async function (message) { + + console.log("-------Kafka consumer log starts here------------------"); + console.log("Topic Name: ", topic); + console.log("Message: ", JSON.stringify(message)); + console.log("-------Kafka consumer log ends here------------------"); + + + if (message && message.topic === SUBMISSION_TOPIC) { + submissionsConsumer.messageReceived(message); + } + // call projectCertificateConsumer + if (message && message.topic === CERTIFICATE_TOPIC) { + projectCertificateConsumer.messageReceived(message); + } + + // call userDelete consumer + if (message && message.topic === USER_DELETE_TOPIC) { + userDeleteConsumer.messageReceived(message); + } - if (message && message.topic === SUBMISSION_TOPIC) { - submissionsConsumer.messageReceived(message); - } - // call projectCertificateConsumer - if (message && message.topic === CERTIFICATE_TOPIC) { - projectCertificateConsumer.messageReceived(message); - } - - // call userDelete consumer - if (message && message.topic === USER_DELETE_TOPIC) { - userDeleteConsumer.messageReceived(message); - } - - }); + }); - consumer.on('error', async function (error) { + consumer.on('error', async function (error) { - if(error.topics && error.topics[0] === SUBMISSION_TOPIC) { - submissionsConsumer.errorTriggered(error); - } - if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { - projectCertificateConsumer.errorTriggered(error); - } + if(error.topics && error.topics[0] === SUBMISSION_TOPIC) { + submissionsConsumer.errorTriggered(error); + } + if(error.topics && error.topics[0] === CERTIFICATE_TOPIC) { + projectCertificateConsumer.errorTriggered(error); + } - if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { - userDeleteConsumer.errorTriggered(error); - } + if (error.topics && error.topics[0] === USER_DELETE_TOPIC) { + userDeleteConsumer.errorTriggered(error); + } - }); + }); - } } - }; module.exports = connect; diff --git a/envVariables.js b/envVariables.js index 427074f4..8cc63ba8 100644 --- a/envVariables.js +++ b/envVariables.js @@ -69,6 +69,11 @@ "USER_DELETE_TOPIC": { message: "Required user delete kafka consumer topic name", optional: true, + requiredIf : { + key: "USER_DELETE_ON_OFF", + operator: "EQUALS", + value: "ON" + } }, "ID": { message: "Required Service ID", @@ -82,6 +87,11 @@ "TELEMETRY_TOPIC": { message: "Required telemetry topic", optional: true, + requiredIf : { + key: "TELEMETRY_ON_OFF", + operator: "EQUALS", + value: "ON" + } }, } From 9afb504104242158f54f64779bc0d566e04d98c4 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 27 Nov 2023 10:10:23 +0530 Subject: [PATCH 340/373] Resolved Comments --- release-notes/7.0.0.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/release-notes/7.0.0.md b/release-notes/7.0.0.md index b23b7838..3ab44b74 100644 --- a/release-notes/7.0.0.md +++ b/release-notes/7.0.0.md @@ -24,7 +24,8 @@ Please note you don't need to deploy the DevOps repo. Once the PR is merged, dep In this release, we have introduced four new environment variables. - USER_DELETE_TOPIC={{user_delete_topic_name | default("")}} - ID={{ml_project_service_id | default("")}} + USER_DELETE_ON_OFF={{user_delete_on_off | default("ON")}} + USER_DELETE_TOPIC={{user_delete_topic_name | default("dev.delete.user")}} + ID={{ml_survey_service_id | default("dev.sunbird.ml.project.service")}} TELEMETRY_ON_OFF={{telemetry_on_off | default("ON")}} - TELEMETRY_TOPIC={{telemetry_raw_topic_name | default("")}} \ No newline at end of file + TELEMETRY_TOPIC={{telemetry_raw_topic_name | default("dev.telemetry.raw"")}} \ No newline at end of file From cb59983468d03836b66d9805c396500881afee35 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Mon, 18 Dec 2023 16:09:32 +0530 Subject: [PATCH 341/373] Added Long Term fix for NVSK --- generics/constants/api-responses.js | 1 + module/userProjects/helper.js | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index db81c809..38d55116 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -136,4 +136,5 @@ module.exports = { "ISSUER_KID_NOT_FOUND" : "Failed to fetch certificate issuer kid", "PROJECT_SUBMITTED_FOR_REISSUE" : "Submitted for project certificate reIssue", "PROGRAM_JOIN_FAILED" : "Failed to join program", + "FAILED_TO_START_RESOURCE": "There was an error in starting/joining. Please try again after some time." }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 463c596c..91e8cedf 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1562,8 +1562,13 @@ module.exports = class UserProjectsHelper { ) { projectCreation.data.userProfile = userProfile.data.response; addReportInfoToSolution = true; - } - } + } else { + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } + } } else { //Fetch user profile information by calling sunbird's user read api. @@ -1575,7 +1580,12 @@ module.exports = class UserProjectsHelper { ) { projectCreation.data.userProfile = userProfileData.data.response; addReportInfoToSolution = true; - } + } else { + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } } projectCreation.data.userRoleInformation = userRoleInformation; From 6325cb83273d3cf1cb462055092b0309bb747e89 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Thu, 21 Dec 2023 14:30:40 +0530 Subject: [PATCH 342/373] Added encEmail delete --- generics/services/users.js | 2 ++ module/userProjects/helper.js | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/generics/services/users.js b/generics/services/users.js index a7961f89..6b9473b8 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -47,6 +47,8 @@ const profile = function ( token,userId = "" ) { "response.prevUsedPhone", "response.prevUsedEmail", "response.recoveryPhone", + "response.encEmail", + "response.encPhone", ]); } else { result.success = false; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 91e8cedf..1737e6e3 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -112,7 +112,9 @@ module.exports = class UserProjectsHelper { "userProfile.prevUsedPhone": 1, "userProfile.prevUsedEmail": 1, "userProfile.recoveryPhone": 1, - "userProfile.dob": 1 + "userProfile.dob": 1, + "userProfile.encEmail": 1, + "userProfile.encPhone": 1 }, }; let deleteUserPIIDataResult = await projectQueries.updateMany(filter, updateProfile) From 4331e50486e75cdc5e37733a6419dd2aa2956edd Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Fri, 12 Jan 2024 02:11:30 +0530 Subject: [PATCH 343/373] worked on validation for req body and db userlocation data --- module/userProjects/helper.js | 97 ++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1737e6e3..80b964fb 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -818,6 +818,7 @@ module.exports = class UserProjectsHelper { if (searchQuery && searchQuery.length > 0) { matchQuery["$match"]["$or"] = searchQuery; } + console.log(pageSize, pageNo, searchQuery, fieldsArray, groupBy,"this is filed array") let projection = {} fieldsArray.forEach(field => { @@ -834,7 +835,8 @@ module.exports = class UserProjectsHelper { aggregateData.push({ $group: groupBy }); - } else { + } + else { aggregateData.push({ $project: projection }); @@ -865,6 +867,8 @@ module.exports = class UserProjectsHelper { let result = await projectQueries.getAggregate(aggregateData); + console.log(result,"after aggregation") + return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECTS_FETCHED, @@ -1281,7 +1285,6 @@ module.exports = class UserProjectsHelper { } let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); - if (projectId === "") { // This will check wether the user user is targeted to solution or not based on his userRoleInformation const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,userRoleInformation,solutionId) @@ -1291,15 +1294,18 @@ module.exports = class UserProjectsHelper { userId: userId, isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true }, ["_id"]); - if( projectDetails.length > 0 ) { - projectId = projectDetails[0]._id; - } else { + // if( projectDetails.length < 0 ) { + // projectId = projectDetails[0]._id; + // } + // else { + let isAPrivateSolution = (targetedSolutionId.data.isATargetedSolution === false) ? true : false; let solutionDetails = {} if( templateId === "" ) { // If solution Id of a private program is passed, fetch solution details if ( isAPrivateSolution && solutionId != "" ) { + console.log("entering private solution") solutionDetails = await solutionsHelper.solutionDocuments({ _id: solutionId, isAPrivateProgram: true @@ -1327,6 +1333,8 @@ module.exports = class UserProjectsHelper { } solutionDetails = solutionDetails[0]; } else { + console.log("entering core solution") + solutionDetails = await coreService.solutionDetailsBasedOnRoleAndLocation( userToken, @@ -1335,6 +1343,8 @@ module.exports = class UserProjectsHelper { isAPrivateSolution ); + console.log(solutionDetails,"this is solution Details based") + if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { throw { status : HTTP_STATUS_CODE["bad_request"].status, @@ -1346,7 +1356,8 @@ module.exports = class UserProjectsHelper { } } else { - + console.log("entering survey solution") + solutionDetails = await surveyService.listSolutions([solutionExternalId]); if( !solutionDetails.success ) { @@ -1363,7 +1374,6 @@ module.exports = class UserProjectsHelper { let queryData = {}; queryData["_id"] = solutionDetails.programId; let programDetails = await programsQueries.programsDocument(queryData,["requestForPIIConsent"]); - // if requestForPIIConsent not there do not call program join if ( programDetails.length > 0 && programDetails[0].hasOwnProperty('requestForPIIConsent')) { @@ -1379,23 +1389,24 @@ module.exports = class UserProjectsHelper { "resourcesStarted" ] ); - + console.log(programUsers,"this ijs programm userrrrrrr") if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { let programJoinBody = {}; programJoinBody.userRoleInformation = userRoleInformation; programJoinBody.isResource = true; programJoinBody.consentShared = true; - let joinProgramData = await coreService.joinProgram ( - solutionDetails.programId, - programJoinBody, - userToken - ); - if ( !joinProgramData.success ) { - return resolve({ - status: HTTP_STATUS_CODE.bad_request.status, - message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - }); - } + // let joinProgramData = await coreService.joinProgram ( + // solutionDetails.programId, + // programJoinBody, + // userToken + // ); + // console.log(joinProgramData,"this is join program data") + // if ( !joinProgramData.success ) { + // return resolve({ + // status: HTTP_STATUS_CODE.bad_request.status, + // message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + // }); + // } } } @@ -1528,6 +1539,7 @@ module.exports = class UserProjectsHelper { // fetch userRoleInformation from observation if referenecFrom is observation let addReportInfoToSolution = false; + if ( getUserProfileFromObservation ){ let observationDetails = await surveyService.observationDetails( @@ -1574,12 +1586,13 @@ module.exports = class UserProjectsHelper { } else { //Fetch user profile information by calling sunbird's user read api. - let userProfileData = await userProfileService.profile(userToken, userId); - if ( userProfileData.success && + if ( userProfileData.success && userProfileData.data && - userProfileData.data.response + // userProfileData.data.response + userProfileData.data ) { + console.log("Enteredthe if statement") projectCreation.data.userProfile = userProfileData.data.response; addReportInfoToSolution = true; } else { @@ -1589,16 +1602,39 @@ module.exports = class UserProjectsHelper { }; } } - projectCreation.data.userRoleInformation = userRoleInformation; - //compare & update userProfile with userRoleInformation + + let getUserLocationfromuserProfile= projectCreation.data.userProfile.userLocations; +// check wherther data passing in body or not + if(!userRoleInformation ){ + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } + + ////check whether userRoleInformation(reqbody) and (db )data matches + +const matchingDistrict = getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'district' && eachLocation.id === userRoleInformation.district); +const matchingState = getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'state' && eachLocation.id === userRoleInformation.state); +const matchingBlock = getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'block' && eachLocation.id === userRoleInformation.block); +const matchingSchool= getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'school' &&eachLocation.code === userRoleInformation.school) +// Throw an error if there is no match +if (!matchingDistrict || !matchingState || !matchingBlock || !matchingSchool) { + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; } + + + /////////// if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( projectCreation.data.userProfile, userRoleInformation ); - + console.log(updatedUserProfile,"updated user profile") if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { projectCreation.data.userProfile = updatedUserProfile.data; } @@ -1616,7 +1652,7 @@ module.exports = class UserProjectsHelper { await kafkaProducersHelper.pushProjectToKafka(project); projectId = project._id; - } + // } } let projectDetails = await this.details( @@ -2229,7 +2265,6 @@ module.exports = class UserProjectsHelper { query["referenceFrom"] = CONSTANTS.common.LINK; } } - let projects = await this.projects( query, pageSize, @@ -2250,7 +2285,7 @@ module.exports = class UserProjectsHelper { "certificate" ] ); - + console.log("================================",projects) let totalCount = 0; let data = []; if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { @@ -4002,7 +4037,7 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles - + console.log(userRoleInformation,userProfile,"this is on api call inside update") if(userRoleInformation.role) { // Check if userRoleInformation has role value. let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. @@ -4078,9 +4113,11 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) // Create location only object from userRoleInformation let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); - + console.log(userRoleInformationLocationObject,"===================this is ====================") // All location keys from userRoleInformation let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); + console.log(userRoleInfomrationLocationKeys,"this is userRoleInformationObject") + let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values From a44b553ca3529f3fcd6296be3977f5aca0b63688 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Fri, 12 Jan 2024 08:02:47 +0530 Subject: [PATCH 344/373] Fix: Prod Obervation led imp with task level obs fix --- module/userProjects/helper.js | 84 ++++++++++++++++++++++++----------- release-notes/7.0.0.md | 2 +- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1737e6e3..45f431fa 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1280,6 +1280,13 @@ module.exports = class UserProjectsHelper { solutionExternalId = templateDocuments[0].solutionExternalId; } + if(bodyData.hasOwnProperty("detailsPayload")){ + let detailsPayload = {...bodyData.detailsPayload} + delete bodyData.detailsPayload + bodyData = {...detailsPayload, ...bodyData} + + } + let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); if (projectId === "") { @@ -1487,39 +1494,62 @@ module.exports = class UserProjectsHelper { getUserProfileFromObservation = true; } projectCreation.data.submissions = bodyData.submissions; + + let entityInformation = + await surveyService.listEntitiesByLocationIds( + userToken, + [bodyData.submissions.entityId] + ); + + if( !entityInformation.success ) { + throw { + message : CONSTANTS.apiResponses.ENTITY_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } + } + + let entityDetails = await _entitiesMetaInformation( + entityInformation.data + ); + + if ( entityDetails && entityDetails.length > 0 ) { + projectCreation.data["entityInformation"] = entityDetails[0]; + } + + projectCreation.data.entityId = entityInformation.data[0]._id; + } + } else { + if( + solutionDetails.entityType && bodyData[solutionDetails.entityType] + ) { + let entityInformation = + await surveyService.listEntitiesByLocationIds( + userToken, + [bodyData[solutionDetails.entityType]] + ); + + if( !entityInformation.success ) { + throw { + message : CONSTANTS.apiResponses.ENTITY_NOT_FOUND, + status : HTTP_STATUS_CODE['bad_request'].status + } + } + + let entityDetails = await _entitiesMetaInformation( + entityInformation.data + ); + + if ( entityDetails && entityDetails.length > 0 ) { + projectCreation.data["entityInformation"] = entityDetails[0]; + } + + projectCreation.data.entityId = entityInformation.data[0]._id; } } if( bodyData.role ) { projectCreation.data["userRole"] = bodyData.role; } - - if( - solutionDetails.entityType && bodyData[solutionDetails.entityType] - ) { - let entityInformation = - await surveyService.listEntitiesByLocationIds( - userToken, - [bodyData[solutionDetails.entityType]] - ); - - if( !entityInformation.success ) { - throw { - message : CONSTANTS.apiResponses.ENTITY_NOT_FOUND, - status : HTTP_STATUS_CODE['bad_request'].status - } - } - - let entityDetails = await _entitiesMetaInformation( - entityInformation.data - ); - - if ( entityDetails && entityDetails.length > 0 ) { - projectCreation.data["entityInformation"] = entityDetails[0]; - } - - projectCreation.data.entityId = entityInformation.data[0]._id; - } } diff --git a/release-notes/7.0.0.md b/release-notes/7.0.0.md index 3ab44b74..169707c2 100644 --- a/release-notes/7.0.0.md +++ b/release-notes/7.0.0.md @@ -4,7 +4,7 @@ This version contains set of manual activites tasks that must be completed in or ### Deploy ml-projects-services -To retrieve the latest release tag for version 7.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-7.0.0_RC1 +To retrieve the latest release tag for version 7.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-7.0.0_RC2 To proceed with the deployment process, follow the steps below: From afe4fd95d212ef392ee42dcd9b1cdd39950e7e46 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Fri, 12 Jan 2024 09:33:07 +0530 Subject: [PATCH 345/373] removing console --- module/userProjects/helper.js | 82 +++++++++++++++++------------------ 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 80b964fb..88e8cad7 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -818,7 +818,6 @@ module.exports = class UserProjectsHelper { if (searchQuery && searchQuery.length > 0) { matchQuery["$match"]["$or"] = searchQuery; } - console.log(pageSize, pageNo, searchQuery, fieldsArray, groupBy,"this is filed array") let projection = {} fieldsArray.forEach(field => { @@ -867,7 +866,6 @@ module.exports = class UserProjectsHelper { let result = await projectQueries.getAggregate(aggregateData); - console.log(result,"after aggregation") return resolve({ success: true, @@ -1305,7 +1303,6 @@ module.exports = class UserProjectsHelper { if( templateId === "" ) { // If solution Id of a private program is passed, fetch solution details if ( isAPrivateSolution && solutionId != "" ) { - console.log("entering private solution") solutionDetails = await solutionsHelper.solutionDocuments({ _id: solutionId, isAPrivateProgram: true @@ -1333,8 +1330,6 @@ module.exports = class UserProjectsHelper { } solutionDetails = solutionDetails[0]; } else { - console.log("entering core solution") - solutionDetails = await coreService.solutionDetailsBasedOnRoleAndLocation( userToken, @@ -1343,7 +1338,6 @@ module.exports = class UserProjectsHelper { isAPrivateSolution ); - console.log(solutionDetails,"this is solution Details based") if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { throw { @@ -1356,8 +1350,6 @@ module.exports = class UserProjectsHelper { } } else { - console.log("entering survey solution") - solutionDetails = await surveyService.listSolutions([solutionExternalId]); if( !solutionDetails.success ) { @@ -1389,7 +1381,6 @@ module.exports = class UserProjectsHelper { "resourcesStarted" ] ); - console.log(programUsers,"this ijs programm userrrrrrr") if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { let programJoinBody = {}; programJoinBody.userRoleInformation = userRoleInformation; @@ -1592,7 +1583,6 @@ module.exports = class UserProjectsHelper { // userProfileData.data.response userProfileData.data ) { - console.log("Enteredthe if statement") projectCreation.data.userProfile = userProfileData.data.response; addReportInfoToSolution = true; } else { @@ -1603,38 +1593,12 @@ module.exports = class UserProjectsHelper { } } projectCreation.data.userRoleInformation = userRoleInformation; - //compare & update userProfile with userRoleInformation - - let getUserLocationfromuserProfile= projectCreation.data.userProfile.userLocations; -// check wherther data passing in body or not - if(!userRoleInformation ){ - throw { - message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, - status: HTTP_STATUS_CODE["failed_dependency"].status, - }; - } - - ////check whether userRoleInformation(reqbody) and (db )data matches - -const matchingDistrict = getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'district' && eachLocation.id === userRoleInformation.district); -const matchingState = getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'state' && eachLocation.id === userRoleInformation.state); -const matchingBlock = getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'block' && eachLocation.id === userRoleInformation.block); -const matchingSchool= getUserLocationfromuserProfile.find(eachLocation => eachLocation.type === 'school' &&eachLocation.code === userRoleInformation.school) -// Throw an error if there is no match -if (!matchingDistrict || !matchingState || !matchingBlock || !matchingSchool) { - throw { - message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, - status: HTTP_STATUS_CODE["failed_dependency"].status, - }; } - - - /////////// + if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( projectCreation.data.userProfile, userRoleInformation ); - console.log(updatedUserProfile,"updated user profile") if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { projectCreation.data.userProfile = updatedUserProfile.data; } @@ -2285,7 +2249,6 @@ if (!matchingDistrict || !matchingState || !matchingBlock || !matchingSchool) { "certificate" ] ); - console.log("================================",projects) let totalCount = 0; let data = []; if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { @@ -4037,7 +4000,13 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles - console.log(userRoleInformation,userProfile,"this is on api call inside update") + //check the data in userRoleInformation + if(!userRoleInformation ){ + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } if(userRoleInformation.role) { // Check if userRoleInformation has role value. let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. @@ -4111,13 +4080,42 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) userProfile.userRoleMismatchFoundAndUpdated = true; } + // Create location only object from userRoleInformation let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); - console.log(userRoleInformationLocationObject,"===================this is ====================") + +////check whether userRoleInformation(reqbody) and (db )data matches +let matchingDistrict, matchingState, matchingBlock, matchingSchool; + +for (const eachLocation of userProfile.userLocations) { + if (!matchingDistrict && eachLocation.type === 'district' && eachLocation.id === userRoleInformationLocationObject.district) { + matchingDistrict = eachLocation; + } + + if (!matchingState && eachLocation.type === 'state' && eachLocation.id === userRoleInformationLocationObject.state) { + matchingState = eachLocation; + } + + if (!matchingBlock && eachLocation.type === 'block' && eachLocation.id === userRoleInformationLocationObject.block) { + matchingBlock = eachLocation; + } + + if (!matchingSchool && eachLocation.type === 'school' && eachLocation.code === userRoleInformationLocationObject.school) { + matchingSchool = eachLocation; + } + + // Break the loop if all variables have been assigned + if (matchingDistrict && matchingState && matchingBlock && matchingSchool) { + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } +} + // All location keys from userRoleInformation - let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); - console.log(userRoleInfomrationLocationKeys,"this is userRoleInformationObject") + let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values From 51534b5e90cd618df44a76e1ed36da23555aec84 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Fri, 12 Jan 2024 10:58:13 +0530 Subject: [PATCH 346/373] validation dynamic and remving commented codes --- module/userProjects/helper.js | 75 +++++++++++++++-------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 88e8cad7..48b5ba40 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1292,10 +1292,10 @@ module.exports = class UserProjectsHelper { userId: userId, isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true }, ["_id"]); - // if( projectDetails.length < 0 ) { - // projectId = projectDetails[0]._id; - // } - // else { + if( projectDetails.length < 0 ) { + projectId = projectDetails[0]._id; + } + else { let isAPrivateSolution = (targetedSolutionId.data.isATargetedSolution === false) ? true : false; let solutionDetails = {} @@ -1386,18 +1386,18 @@ module.exports = class UserProjectsHelper { programJoinBody.userRoleInformation = userRoleInformation; programJoinBody.isResource = true; programJoinBody.consentShared = true; - // let joinProgramData = await coreService.joinProgram ( - // solutionDetails.programId, - // programJoinBody, - // userToken - // ); - // console.log(joinProgramData,"this is join program data") - // if ( !joinProgramData.success ) { - // return resolve({ - // status: HTTP_STATUS_CODE.bad_request.status, - // message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED - // }); - // } + let joinProgramData = await coreService.joinProgram ( + solutionDetails.programId, + programJoinBody, + userToken + ); + console.log(joinProgramData,"this is join program data") + if ( !joinProgramData.success ) { + return resolve({ + status: HTTP_STATUS_CODE.bad_request.status, + message: CONSTANTS.apiResponses.PROGRAM_JOIN_FAILED + }); + } } } @@ -1580,8 +1580,7 @@ module.exports = class UserProjectsHelper { let userProfileData = await userProfileService.profile(userToken, userId); if ( userProfileData.success && userProfileData.data && - // userProfileData.data.response - userProfileData.data + userProfileData.data.response ) { projectCreation.data.userProfile = userProfileData.data.response; addReportInfoToSolution = true; @@ -1616,9 +1615,9 @@ module.exports = class UserProjectsHelper { await kafkaProducersHelper.pushProjectToKafka(project); projectId = project._id; - // } + } } - + let projectDetails = await this.details( projectId, userId, @@ -4084,34 +4083,24 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) // Create location only object from userRoleInformation let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); -////check whether userRoleInformation(reqbody) and (db )data matches -let matchingDistrict, matchingState, matchingBlock, matchingSchool; - -for (const eachLocation of userProfile.userLocations) { - if (!matchingDistrict && eachLocation.type === 'district' && eachLocation.id === userRoleInformationLocationObject.district) { - matchingDistrict = eachLocation; - } - - if (!matchingState && eachLocation.type === 'state' && eachLocation.id === userRoleInformationLocationObject.state) { - matchingState = eachLocation; - } - - if (!matchingBlock && eachLocation.type === 'block' && eachLocation.id === userRoleInformationLocationObject.block) { - matchingBlock = eachLocation; - } - - if (!matchingSchool && eachLocation.type === 'school' && eachLocation.code === userRoleInformationLocationObject.school) { - matchingSchool = eachLocation; - } +//check whether userRoleInformation(reqbody) and (db )data matches - // Break the loop if all variables have been assigned - if (matchingDistrict && matchingState && matchingBlock && matchingSchool) { - throw { +for (const key in userRoleInformationLocationObject) { + const matchingUserLocationData= userProfile.userLocations.find(eachLocation => { + if (key === 'school') { + return eachLocation.type === 'school' && eachLocation.code === userRoleInformationLocationObject[key]; + } else { + return eachLocation.type === key && eachLocation.id === userRoleInformationLocationObject[key]; + } + } + ) + if (!matchingUserLocationData) { + throw { message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, status: HTTP_STATUS_CODE["failed_dependency"].status, }; + } } -} // All location keys from userRoleInformation From afb9c723064de35a4757ee062d25837bd0083de1 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Fri, 12 Jan 2024 13:34:30 +0530 Subject: [PATCH 347/373] pr modification for validation --- module/userProjects/helper.js | 50 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 48b5ba40..118d06fc 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1292,7 +1292,7 @@ module.exports = class UserProjectsHelper { userId: userId, isAPrivateProgram: targetedSolutionId.data.isATargetedSolution ? false : true }, ["_id"]); - if( projectDetails.length < 0 ) { + if( projectDetails.length > 0 ) { projectId = projectDetails[0]._id; } else { @@ -1391,7 +1391,6 @@ module.exports = class UserProjectsHelper { programJoinBody, userToken ); - console.log(joinProgramData,"this is join program data") if ( !joinProgramData.success ) { return resolve({ status: HTTP_STATUS_CODE.bad_request.status, @@ -3999,13 +3998,7 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles - //check the data in userRoleInformation - if(!userRoleInformation ){ - throw { - message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, - status: HTTP_STATUS_CODE["failed_dependency"].status, - }; - } + if(userRoleInformation.role) { // Check if userRoleInformation has role value. let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. @@ -4083,24 +4076,29 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) // Create location only object from userRoleInformation let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); -//check whether userRoleInformation(reqbody) and (db )data matches + // To check all the keys of userRoleInformation is there in an userProfile.userLocation + const missingUserLocationstypeKeys = Object.keys(userRoleInformationLocationObject).filter(key => !userProfile.userLocations.some(eachLocation => eachLocation.type === key)); -for (const key in userRoleInformationLocationObject) { - const matchingUserLocationData= userProfile.userLocations.find(eachLocation => { - if (key === 'school') { - return eachLocation.type === 'school' && eachLocation.code === userRoleInformationLocationObject[key]; - } else { - return eachLocation.type === key && eachLocation.id === userRoleInformationLocationObject[key]; - } - } - ) - if (!matchingUserLocationData) { - throw { - message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, - status: HTTP_STATUS_CODE["failed_dependency"].status, - }; - } - } + //check whether userRoleInformation(reqbody) and (db )data matches + + for (const key in userRoleInformationLocationObject) { + const matchingUserLocationData= userProfile.userLocations.find(eachLocation => { + if (key === 'school') { + return eachLocation.type === 'school' && eachLocation.code === userRoleInformationLocationObject[key]; + } else { + return eachLocation.type === key && eachLocation.id === userRoleInformationLocationObject[key]; + } + } + ) + //check the data in userRoleInformation + + if (!userRoleInformation || !matchingUserLocationData || missingUserLocationstypeKeys.length > 0 ) { + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } + } // All location keys from userRoleInformation From ddad1f5ca524db4e0041c621d339b16daacc9ccb Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Fri, 12 Jan 2024 15:42:59 +0530 Subject: [PATCH 348/373] resolveing PR comments --- module/userProjects/helper.js | 74 ++++++++++++++++------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 118d06fc..d952ad57 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -834,8 +834,7 @@ module.exports = class UserProjectsHelper { aggregateData.push({ $group: groupBy }); - } - else { + } else { aggregateData.push({ $project: projection }); @@ -866,7 +865,6 @@ module.exports = class UserProjectsHelper { let result = await projectQueries.getAggregate(aggregateData); - return resolve({ success: true, message: CONSTANTS.apiResponses.PROJECTS_FETCHED, @@ -1283,6 +1281,7 @@ module.exports = class UserProjectsHelper { } let userRoleInformation = _.omit(bodyData,["referenceFrom","submissions","hasAcceptedTAndC","link"]); + if (projectId === "") { // This will check wether the user user is targeted to solution or not based on his userRoleInformation const targetedSolutionId = await coreService.checkIfSolutionIsTargetedForUserProfile(userToken,userRoleInformation,solutionId) @@ -1294,9 +1293,7 @@ module.exports = class UserProjectsHelper { }, ["_id"]); if( projectDetails.length > 0 ) { projectId = projectDetails[0]._id; - } - else { - + } else { let isAPrivateSolution = (targetedSolutionId.data.isATargetedSolution === false) ? true : false; let solutionDetails = {} @@ -1338,7 +1335,6 @@ module.exports = class UserProjectsHelper { isAPrivateSolution ); - if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { throw { status : HTTP_STATUS_CODE["bad_request"].status, @@ -1350,6 +1346,7 @@ module.exports = class UserProjectsHelper { } } else { + solutionDetails = await surveyService.listSolutions([solutionExternalId]); if( !solutionDetails.success ) { @@ -1366,6 +1363,7 @@ module.exports = class UserProjectsHelper { let queryData = {}; queryData["_id"] = solutionDetails.programId; let programDetails = await programsQueries.programsDocument(queryData,["requestForPIIConsent"]); + // if requestForPIIConsent not there do not call program join if ( programDetails.length > 0 && programDetails[0].hasOwnProperty('requestForPIIConsent')) { @@ -1381,6 +1379,7 @@ module.exports = class UserProjectsHelper { "resourcesStarted" ] ); + if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { let programJoinBody = {}; programJoinBody.userRoleInformation = userRoleInformation; @@ -1529,7 +1528,6 @@ module.exports = class UserProjectsHelper { // fetch userRoleInformation from observation if referenecFrom is observation let addReportInfoToSolution = false; - if ( getUserProfileFromObservation ){ let observationDetails = await surveyService.observationDetails( @@ -1576,8 +1574,9 @@ module.exports = class UserProjectsHelper { } else { //Fetch user profile information by calling sunbird's user read api. + let userProfileData = await userProfileService.profile(userToken, userId); - if ( userProfileData.success && + if ( userProfileData.success && userProfileData.data && userProfileData.data.response ) { @@ -1590,18 +1589,37 @@ module.exports = class UserProjectsHelper { }; } } + projectCreation.data.userRoleInformation = userRoleInformation; - + + //compare & update userProfile with userRoleInformation if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { + + if(!userRoleInformation){ + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } + let locationsDataKeys = Object.keys(_.omit(userRoleInformation,["role"])) let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( projectCreation.data.userProfile, userRoleInformation ); + if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { projectCreation.data.userProfile = updatedUserProfile.data; } + for(let i = 0; i <= locationsDataKeys.length; i++){ + let dataPresent = projectCreation.data.userProfile.userLocations.find(e=> locationsDataKeys[i] === e.type) + if(!dataPresent){ + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } + } } - let project = await projectQueries.createProject(projectCreation.data); if ( addReportInfoToSolution && project.solutionId ) { @@ -1616,7 +1634,7 @@ module.exports = class UserProjectsHelper { projectId = project._id; } } - + let projectDetails = await this.details( projectId, userId, @@ -2227,6 +2245,7 @@ module.exports = class UserProjectsHelper { query["referenceFrom"] = CONSTANTS.common.LINK; } } + let projects = await this.projects( query, pageSize, @@ -2247,6 +2266,7 @@ module.exports = class UserProjectsHelper { "certificate" ] ); + let totalCount = 0; let data = []; if( projects.success && projects.data && projects.data.data && Object.keys(projects.data.data).length > 0 ) { @@ -3998,7 +4018,7 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) let updateUserProfileRoleInformation = false; // Flag to see if roleInformation i.e. userProfile.profileUserTypes has to be updated based on userRoleInfromation.roles - + if(userRoleInformation.role) { // Check if userRoleInformation has role value. let rolesInUserRoleInformation = userRoleInformation.role.split(","); // userRoleInfomration.role can be multiple with comma separated. @@ -4072,36 +4092,10 @@ function _updateUserProfileBasedOnUserRoleInfo(userProfile, userRoleInformation) userProfile.userRoleMismatchFoundAndUpdated = true; } - // Create location only object from userRoleInformation let userRoleInformationLocationObject = _.omit(userRoleInformation, ['role']); - - // To check all the keys of userRoleInformation is there in an userProfile.userLocation - const missingUserLocationstypeKeys = Object.keys(userRoleInformationLocationObject).filter(key => !userProfile.userLocations.some(eachLocation => eachLocation.type === key)); - - //check whether userRoleInformation(reqbody) and (db )data matches - - for (const key in userRoleInformationLocationObject) { - const matchingUserLocationData= userProfile.userLocations.find(eachLocation => { - if (key === 'school') { - return eachLocation.type === 'school' && eachLocation.code === userRoleInformationLocationObject[key]; - } else { - return eachLocation.type === key && eachLocation.id === userRoleInformationLocationObject[key]; - } - } - ) - //check the data in userRoleInformation - - if (!userRoleInformation || !matchingUserLocationData || missingUserLocationstypeKeys.length > 0 ) { - throw { - message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, - status: HTTP_STATUS_CODE["failed_dependency"].status, - }; - } - } - + // All location keys from userRoleInformation - let userRoleInfomrationLocationKeys = Object.keys(userRoleInformationLocationObject); let updateUserProfileLocationInformation = false; // Flag to see if userLocations i.e. userProfile.userLocations has to be updated based on userRoleInfromation location values From faedd674e669e1fc710ef32320da81baddf6c622 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Fri, 12 Jan 2024 16:16:50 +0530 Subject: [PATCH 349/373] comment and name change on validation --- module/userProjects/helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index d952ad57..042a6f4a 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1610,8 +1610,9 @@ module.exports = class UserProjectsHelper { if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { projectCreation.data.userProfile = updatedUserProfile.data; } + // checking the reqbody data and userLocation type matches or not for(let i = 0; i <= locationsDataKeys.length; i++){ - let dataPresent = projectCreation.data.userProfile.userLocations.find(e=> locationsDataKeys[i] === e.type) + let dataPresent = projectCreation.data.userProfile.userLocations.find(eachLocationType=> locationsDataKeys[i] === eachLocationType.type) if(!dataPresent){ throw { message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, From 7ed2c29dc8ba7321c43a3f9426d58677067f0b11 Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Tue, 16 Jan 2024 15:53:44 +0530 Subject: [PATCH 350/373] Fix: Prod Obervation led imp with task level obs fix --- generics/constants/api-responses.js | 3 +- generics/helpers/utils.js | 42 ++++++++++++++++- module/entities/helper.js | 70 +++++++++++++++++++++++++++++ module/userProjects/helper.js | 7 ++- 4 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 module/entities/helper.js diff --git a/generics/constants/api-responses.js b/generics/constants/api-responses.js index 38d55116..84d0c7ff 100644 --- a/generics/constants/api-responses.js +++ b/generics/constants/api-responses.js @@ -136,5 +136,6 @@ module.exports = { "ISSUER_KID_NOT_FOUND" : "Failed to fetch certificate issuer kid", "PROJECT_SUBMITTED_FOR_REISSUE" : "Submitted for project certificate reIssue", "PROGRAM_JOIN_FAILED" : "Failed to join program", - "FAILED_TO_START_RESOURCE": "There was an error in starting/joining. Please try again after some time." + "FAILED_TO_START_RESOURCE": "There was an error in starting/joining. Please try again after some time.", + "ENTITY_FETCHED": "Entities fetched successfull", }; diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index ea285087..9f146a5f 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -421,6 +421,44 @@ function generateUUId() { return telemetryEvent; } + +/** + * check the uuid is valid + * @function + * @name checkIfValidUUID + * @returns {String} returns boolean. +*/ + +function checkIfValidUUID(value) { + const regexExp = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi; + return regexExp.test(value); +} + +/** + * filter out location id and code + * @function + * @name filterLocationIdandCode + * @returns {Object} - Object contain locationid and location code array. +*/ + +function filterLocationIdandCode(dataArray) { + let locationIds = []; + let locationCodes = []; + dataArray.forEach(element=>{ + if (this.checkIfValidUUID(element)) { + locationIds.push(element); + } else { + locationCodes.push(element); + } + }); + return ({ + ids : locationIds, + codes : locationCodes + }); +} + + + module.exports = { camelCaseToTitleCase : camelCaseToTitleCase, lowerCase : lowerCase, @@ -439,5 +477,7 @@ module.exports = { noOfElementsInArray : noOfElementsInArray, operatorValidation : operatorValidation, generateTelemetryEventSkeletonStructure : generateTelemetryEventSkeletonStructure, - generateTelemetryEvent : generateTelemetryEvent + generateTelemetryEvent : generateTelemetryEvent, + filterLocationIdandCode : filterLocationIdandCode, + checkIfValidUUID : checkIfValidUUID }; diff --git a/module/entities/helper.js b/module/entities/helper.js new file mode 100644 index 00000000..735c0729 --- /dev/null +++ b/module/entities/helper.js @@ -0,0 +1,70 @@ +/** + * name : helper.js + * author : Ankit Shahu + * created-date : 16-Jan-2024 + * Description : entities helper functionality. + */ + +const userProfileService = require(GENERICS_FILES_PATH + "/services/users"); + +module.exports = class entitieHelper { + + /** + * update registry in entities. + * @method + * @name listByLocationIds + * @param {Object} locationIds - locationIds + * @returns {Object} entity Document + */ + + static listByLocationIds(locationIds) { + return new Promise(async (resolve, reject) => { + try { + //if not uuid considering as location code- for school. + let locationDeatails = UTILS.filterLocationIdandCode(locationIds,); + //set request body for learners api + let entityInformation = []; + let formatResult = true; + + if ( locationDeatails.ids.length > 0 ) { + let bodyData = { + "id" : locationDeatails.ids + } + let entityData = await userProfileService.locationSearch( bodyData, formatResult ); + if ( entityData.success ) { + entityInformation = entityData.data; + } + } + + if ( locationDeatails.codes.length > 0 ) { + let bodyData = { + "code" : locationDeatails.codes + } + let entityData = await userProfileService.locationSearch( bodyData, formatResult ); + if ( entityData.success ) { + entityInformation = entityInformation.concat(entityData.data); + } + } + + if ( !entityInformation.length > 0 ) { + throw { + message : CONSTANTS.apiResponses.ENTITY_NOT_FOUND + } + } + + return resolve({ + success : true, + message : CONSTANTS.apiResponses.ENTITY_FETCHED, + data : entityInformation + }); + + } catch(error) { + return resolve({ + success : false, + message : error.message + }); + } + }) + } + +} \ No newline at end of file diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 45f431fa..84f18d79 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -29,6 +29,7 @@ const certificateValidationsHelper = require(MODULES_BASE_PATH + "/certificateVa const _ = require("lodash"); const programUsersQueries = require(DB_QUERY_BASE_PATH + "/programUsers"); const telemetryEventOnOff = process.env.TELEMETRY_ON_OFF +const entitieHelper = require(MODULES_BASE_PATH + "/entities/helper") /** * UserProjectsHelper * @class @@ -1496,8 +1497,7 @@ module.exports = class UserProjectsHelper { projectCreation.data.submissions = bodyData.submissions; let entityInformation = - await surveyService.listEntitiesByLocationIds( - userToken, + await entitieHelper.listByLocationIds( [bodyData.submissions.entityId] ); @@ -1523,8 +1523,7 @@ module.exports = class UserProjectsHelper { solutionDetails.entityType && bodyData[solutionDetails.entityType] ) { let entityInformation = - await surveyService.listEntitiesByLocationIds( - userToken, + await entitieHelper.listByLocationIds( [bodyData[solutionDetails.entityType]] ); From 4f49b58157cd1e4f34eab5d8d144a4fa1bdab83f Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 17 Jan 2024 11:32:15 +0530 Subject: [PATCH 351/373] Fix: NVSK Long term fix --- module/userProjects/helper.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 17cbe2c7..d9dfe5bb 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1624,12 +1624,6 @@ module.exports = class UserProjectsHelper { //compare & update userProfile with userRoleInformation if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { - if(!userRoleInformation){ - throw { - message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, - status: HTTP_STATUS_CODE["failed_dependency"].status, - }; - } let locationsDataKeys = Object.keys(_.omit(userRoleInformation,["role"])) let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( projectCreation.data.userProfile, @@ -1641,7 +1635,7 @@ module.exports = class UserProjectsHelper { } // checking the reqbody data and userLocation type matches or not for(let i = 0; i <= locationsDataKeys.length; i++){ - let dataPresent = projectCreation.data.userProfile.userLocations.find(eachLocationType=> locationsDataKeys[i] === eachLocationType.type) + let dataPresent = projectCreation.data.userProfile.userLocations.find(eachLocationType=> userRoleInformation[eachLocationType] === eachLocationType[i]) if(!dataPresent){ throw { message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, From ad023548eb4c75982866be42edbeb82e26eba57e Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 17 Jan 2024 15:54:16 +0530 Subject: [PATCH 352/373] Fix: NVSK Long term fix --- module/userProjects/helper.js | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index d9dfe5bb..461e93af 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1624,7 +1624,6 @@ module.exports = class UserProjectsHelper { //compare & update userProfile with userRoleInformation if ( projectCreation.data.userProfile && userRoleInformation && Object.keys(userRoleInformation).length > 0 && Object.keys(projectCreation.data.userProfile).length > 0 ) { - let locationsDataKeys = Object.keys(_.omit(userRoleInformation,["role"])) let updatedUserProfile = await _updateUserProfileBasedOnUserRoleInfo( projectCreation.data.userProfile, userRoleInformation @@ -1633,16 +1632,25 @@ module.exports = class UserProjectsHelper { if (updatedUserProfile && updatedUserProfile.success == true && updatedUserProfile.profileMismatchFound == true) { projectCreation.data.userProfile = updatedUserProfile.data; } - // checking the reqbody data and userLocation type matches or not - for(let i = 0; i <= locationsDataKeys.length; i++){ - let dataPresent = projectCreation.data.userProfile.userLocations.find(eachLocationType=> userRoleInformation[eachLocationType] === eachLocationType[i]) - if(!dataPresent){ - throw { - message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, - status: HTTP_STATUS_CODE["failed_dependency"].status, - }; - } - } + // checking the reqbody data and userLocation type matches or not + for (let key in userRoleInformation) { + // Skip role validation + if (key === 'role') { + continue; + } + let dataPresent; + if (key === 'school') { + dataPresent = projectCreation.data.userProfile.userLocations.find(location => location.code === userRoleInformation[key]); + } else { + dataPresent = projectCreation.data.userProfile.userLocations.find(location => location.id === userRoleInformation[key]); + } + if (!dataPresent) { + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; + } + } } let project = await projectQueries.createProject(projectCreation.data); From 5735e0a72d9640bc2d080b645583eeb87b5a61ef Mon Sep 17 00:00:00 2001 From: ankitshahu Date: Wed, 17 Jan 2024 16:45:33 +0530 Subject: [PATCH 353/373] Fix: NVSK Long term fix --- module/userProjects/helper.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 461e93af..894d3560 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1651,6 +1651,11 @@ module.exports = class UserProjectsHelper { }; } } + } else { + throw { + message: CONSTANTS.apiResponses.FAILED_TO_START_RESOURCE, + status: HTTP_STATUS_CODE["failed_dependency"].status, + }; } let project = await projectQueries.createProject(projectCreation.data); From 79b10f7037e0a7923fe6fb9edb187f04e92249fd Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Thu, 14 Mar 2024 16:03:11 +0530 Subject: [PATCH 354/373] upgrading node from 12 to 18 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 32acaa63..6c9d390e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:12 +FROM node:18 WORKDIR /opt/projects From 2e1c995b333cced3fce38b118cb01f9315801782 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Thu, 21 Mar 2024 17:56:18 +0530 Subject: [PATCH 355/373] security_issue-fixes --- generics/middleware/authenticator.js | 2 +- generics/middleware/validator/index.js | 2 +- package.json | 2 +- routes/index.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index b34628ab..b33e8879 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -101,7 +101,7 @@ module.exports = async function (req, res, next, token = "") { const kid = decoded.header.kid let cert = ""; - let path = keyCloakPublicKeyPath + kid; + let path = keyCloakPublicKeyPath + kid.replace(/\.\.\//g, ''); if (fs.existsSync(path)) { diff --git a/generics/middleware/validator/index.js b/generics/middleware/validator/index.js index c136727a..c06ba317 100644 --- a/generics/middleware/validator/index.js +++ b/generics/middleware/validator/index.js @@ -19,7 +19,7 @@ module.exports = (req, res, next) => { PROJECT_ROOT_DIRECTORY + `/module/${req.params.controller}/validator/${req.params.version}.js`; } - if (fs.existsSync(validatorPath)) require(validatorPath)(req); + if (fs.existsSync(validatorPath)) require(validatorPath.replace(/\.\.\//g, ''))(req); next(); diff --git a/package.json b/package.json index bf152a68..e6d56131 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "keycloak-auth-utils": "^3.3.0", "lodash": "^4.17.15", "log": "^1.4.0", - "mocha": "^6.2.2", + "mocha": "^10.1.0", "moment-timezone": "^0.5.31", "mongoose": "^5.9.4", "mongoose-autopopulate": "^0.12.0", diff --git a/routes/index.js b/routes/index.js index d9ada824..a11d4bba 100644 --- a/routes/index.js +++ b/routes/index.js @@ -64,7 +64,7 @@ module.exports = function (app) { 'attachment; filename=' + result.fileNameWithPath.split('/').pop() ); res.set('Content-Type', 'application/octet-stream'); - fs.createReadStream(result.fileNameWithPath).pipe(res); + fs.createReadStream(result.fileNameWithPath.replace(/\.\.\//g, '')).pipe(res); } else { From 6b63511d3fc9408cb8b95c0c29a300bc6e09e396 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Thu, 28 Mar 2024 15:58:11 +0530 Subject: [PATCH 356/373] code quality bug fixes --- generics/helpers/utils.js | 4 +-- module/certificateValidations/helper.js | 6 ++-- module/library/categories/helper.js | 2 +- module/project/templateTasks/helper.js | 6 ++-- module/project/templates/helper.js | 14 ++++----- module/reports/helper.js | 4 +-- module/userProjects/helper.js | 41 +++++++++++++------------ 7 files changed, 39 insertions(+), 38 deletions(-) diff --git a/generics/helpers/utils.js b/generics/helpers/utils.js index ea285087..07ee66df 100644 --- a/generics/helpers/utils.js +++ b/generics/helpers/utils.js @@ -312,10 +312,10 @@ function createComparableDates(dateArg1, dateArg2) { */ function noOfElementsInArray(data, filter = {}) { - if ( !filter || !Object.keys(filter).length > 0 ) { + if ( !filter || !(Object.keys(filter).length > 0) ) { return data.length; } - if ( !data.length > 0 ) { + if ( !(data.length > 0) ) { return 0; } else { if ( filter.value == "all" ){ diff --git a/module/certificateValidations/helper.js b/module/certificateValidations/helper.js index 82a591cb..3f091862 100644 --- a/module/certificateValidations/helper.js +++ b/module/certificateValidations/helper.js @@ -167,7 +167,7 @@ function _validateCriteriaConditions(condition, data) { } else { return resolve(result) } - if ( !tasksAttachments.length > 0 ) { + if ( !(tasksAttachments.length > 0) ) { return resolve(result) } // get task attachments count @@ -207,8 +207,8 @@ function _criteriaExpressionValidation(expression, keys, result) { try { if( expression == "" || - !keys.length > 0 || - !result.length > 0 || + !(keys.length > 0) || + !(result.length > 0) || keys.length != result.length ) { return resolve(false); } diff --git a/module/library/categories/helper.js b/module/library/categories/helper.js index 042761cc..2e07a3bc 100644 --- a/module/library/categories/helper.js +++ b/module/library/categories/helper.js @@ -192,7 +192,7 @@ module.exports = class LibraryCategoriesHelper { "isDeleted" : false, }, "all", ["__v"]); - if( !projectsData.length > 0 ) { + if( !(projectsData.length > 0 )) { throw { status : HTTP_STATUS_CODE['bad_request'].status, message : CONSTANTS.apiResponses.PROJECT_NOT_FOUND, diff --git a/module/project/templateTasks/helper.js b/module/project/templateTasks/helper.js index 615cc938..f7f2ff05 100644 --- a/module/project/templateTasks/helper.js +++ b/module/project/templateTasks/helper.js @@ -97,7 +97,7 @@ module.exports = class ProjectTemplateTasksHelper { _id : projectTemplateId },["_id","entityType","externalId", "taskSequence"]); - if( !projectTemplate.length > 0 ) { + if( !(projectTemplate.length > 0) ) { throw { message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, status : HTTP_STATUS_CODE['bad_request'].status @@ -627,7 +627,7 @@ module.exports = class ProjectTemplateTasksHelper { if ( !currentData._SYSTEM_ID || - !currentData._SYSTEM_ID === "" || + !(currentData._SYSTEM_ID === "")|| !csvData.data.tasks[currentData["_SYSTEM_ID"]] ) { currentData.STATUS = @@ -815,7 +815,7 @@ module.exports = class ProjectTemplateTasksHelper { let taskDocument = await projectTemplateTaskQueries.taskDocuments(findQuery, ["_id"]); - if ( !taskDocument.length > 0 ) { + if ( !(taskDocument.length > 0) ) { throw { status : HTTP_STATUS_CODE.bad_request.status, message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_TASKS_NOT_FOUND diff --git a/module/project/templates/helper.js b/module/project/templates/helper.js index 588db9ed..4d6e86a9 100644 --- a/module/project/templates/helper.js +++ b/module/project/templates/helper.js @@ -80,7 +80,7 @@ module.exports = class ProjectTemplatesHelper { ["externalId", "name"] ); - if (!categories.length > 0) { + if (!(categories.length > 0)) { throw { status: HTTP_STATUS_CODE["bad_request"].status, message: CONSTANTS.apiResponses.LIBRARY_CATEGORIES_NOT_FOUND, @@ -553,7 +553,7 @@ module.exports = class ProjectTemplatesHelper { } ); - if (!projectTemplateData.length > 0) { + if (!(projectTemplateData.length > 0)) { throw new Error(CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND); } @@ -939,7 +939,7 @@ module.exports = class ProjectTemplatesHelper { ["title", "metaInformation.goal", "externalId"] ); - if (!templateData.length > 0) { + if (!(templateData.length > 0)) { throw { status: HTTP_STATUS_CODE.bad_request.status, message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, @@ -998,7 +998,7 @@ module.exports = class ProjectTemplatesHelper { ] ); - if (!solutionDocument.length > 0) { + if (!(solutionDocument.length > 0)) { throw { message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, status: HTTP_STATUS_CODE["bad_request"].status, @@ -1044,7 +1044,7 @@ module.exports = class ProjectTemplatesHelper { ] ); - if (!templateData.length > 0) { + if (!(templateData.length > 0)) { throw { status: HTTP_STATUS_CODE.bad_request.status, message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, @@ -1063,7 +1063,7 @@ module.exports = class ProjectTemplatesHelper { ); //certificate template data do not exists. - if (!certificateTemplateDetails.length > 0) { + if (!(certificateTemplateDetails.length > 0)) { throw { message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND, }; @@ -1211,7 +1211,7 @@ module.exports = class ProjectTemplatesHelper { ["_id"] ); - if (!templateDocument.length > 0) { + if (!(templateDocument.length > 0)) { throw { status: HTTP_STATUS_CODE.bad_request.status, message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, diff --git a/module/reports/helper.js b/module/reports/helper.js index 9318a6a2..bd9ca111 100644 --- a/module/reports/helper.js +++ b/module/reports/helper.js @@ -102,7 +102,7 @@ module.exports = class ReportsHelper { }); - if ( !projectDetails.length > 0 ) { + if ( !(projectDetails.length > 0)) { if (getPdf == true) { @@ -522,7 +522,7 @@ module.exports = class ReportsHelper { [] ); - if (!projectDetails.length > 0) { + if (!(projectDetails.length > 0)) { return resolve({ message: CONSTANTS.apiResponses.REPORTS_DATA_NOT_FOUND, diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 1737e6e3..464ea6e9 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -242,7 +242,7 @@ module.exports = class UserProjectsHelper { "status" ]); - if (!userProject.length > 0) { + if (!(userProject.length > 0)) { throw { status: HTTP_STATUS_CODE['bad_request'].status, @@ -750,7 +750,7 @@ module.exports = class UserProjectsHelper { "__v" ]); - if (!projectDetails.length > 0) { + if (!(projectDetails.length > 0)) { throw { status: HTTP_STATUS_CODE["bad_request"].status, @@ -760,7 +760,7 @@ module.exports = class UserProjectsHelper { if (Object.keys(userRoleInformation).length > 0) { - if (!projectDetails[0].userRoleInformation || !Object.keys(projectDetails[0].userRoleInformation).length > 0) { + if (!projectDetails[0].userRoleInformation || !(Object.keys(projectDetails[0].userRoleInformation).length > 0)) { await projectQueries.findOneAndUpdate({ _id: projectId },{ @@ -966,7 +966,7 @@ module.exports = class UserProjectsHelper { let tasks = await this.tasks(projectId, taskIds); - if (!tasks.success || !tasks.data.length > 0) { + if (!tasks.success || !(tasks.data.length > 0)) { throw { status: HTTP_STATUS_CODE['bad_request'].status, @@ -1082,7 +1082,7 @@ module.exports = class UserProjectsHelper { let submissions = currentTask.submissions && currentTask.submissions.length > 0 ? currentTask.submissions : [] ; // if submission array is empty - if ( !submissions && !submissions.length > 0 ) { + if ( !submissions && !(submissions.length > 0) ) { updateSubmission.push(updatedData); } @@ -1148,7 +1148,7 @@ module.exports = class UserProjectsHelper { "projectTemplateId" ] ); - if (!project.length > 0) { + if (!(project.length > 0)) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND @@ -1269,7 +1269,7 @@ module.exports = class UserProjectsHelper { "solutionId" : { $exists : true } },["solutionId","solutionExternalId"]); - if( !templateDocuments.length > 0 ) { + if( !(templateDocuments.length > 0) ) { throw { message : CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, status : HTTP_STATUS_CODE['bad_request'].status @@ -1319,7 +1319,7 @@ module.exports = class UserProjectsHelper { "language", "creator" ]); - if( !solutionDetails.length > 0 ) { + if( !(solutionDetails.length > 0) ) { throw { status : HTTP_STATUS_CODE["bad_request"].status, message : CONSTANTS.apiResponses.SOLUTION_NOT_FOUND @@ -1335,7 +1335,7 @@ module.exports = class UserProjectsHelper { isAPrivateSolution ); - if( !solutionDetails.success || (solutionDetails.data.data && !solutionDetails.data.data.length > 0) ) { + if( !solutionDetails.success || (solutionDetails.data.data && !(solutionDetails.data.data.length > 0)) ) { throw { status : HTTP_STATUS_CODE["bad_request"].status, message : CONSTANTS.apiResponses.SOLUTION_DOES_NOT_EXISTS_IN_SCOPE @@ -1380,7 +1380,7 @@ module.exports = class UserProjectsHelper { ] ); - if (!programUsers.length > 0 || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { + if (!(programUsers.length > 0) || ( programUsers.length > 0 && programUsers[0].resourcesStarted == false)) { let programJoinBody = {}; programJoinBody.userRoleInformation = userRoleInformation; programJoinBody.isResource = true; @@ -1534,6 +1534,7 @@ module.exports = class UserProjectsHelper { userToken, bodyData.submissions.observationId ); + console.log(observationDetails) if( observationDetails.data && Object.keys(observationDetails.data).length > 0 && @@ -1691,7 +1692,7 @@ module.exports = class UserProjectsHelper { "averageRating" ]); - if (!projectTemplateData.length > 0) { + if (!(projectTemplateData.length > 0)) { throw { message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, status: HTTP_STATUS_CODE['bad_request'].status @@ -1862,7 +1863,7 @@ module.exports = class UserProjectsHelper { "isAPrivateProgram" ] ); - if( !programDetails.length > 0 ){ + if( !(programDetails.length > 0) ){ throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.PROGRAM_NOT_FOUND @@ -2457,7 +2458,7 @@ module.exports = class UserProjectsHelper { if ( libraryProjects.data && - !Object.keys(libraryProjects.data).length > 0 + !(Object.keys(libraryProjects.data).length > 0) ) { throw { message: CONSTANTS.apiResponses.PROJECT_TEMPLATE_NOT_FOUND, @@ -2702,7 +2703,7 @@ module.exports = class UserProjectsHelper { _id: projectId, }, "all"); - if (!projectDetails.length > 0) { + if (!(projectDetails.length > 0)) { throw { status: HTTP_STATUS_CODE["bad_request"].status, @@ -2848,7 +2849,7 @@ module.exports = class UserProjectsHelper { },["issuer","solutionId","programId"]); //certificate template data do not exists. - if ( !certificateTemplateDetails.length > 0 ) { + if ( !(certificateTemplateDetails.length > 0) ) { throw { message: CONSTANTS.apiResponses.CERTIFICATE_TEMPLATE_NOT_FOUND }; @@ -2998,7 +2999,7 @@ module.exports = class UserProjectsHelper { updateObject ); - if ( projectDetails == null || !Object.keys(projectDetails).length > 0 ) { + if ( projectDetails == null || !(Object.keys(projectDetails).length > 0) ) { throw { status: HTTP_STATUS_CODE["bad_request"].status, message: CONSTANTS.apiResponses.PROJECT_NOT_FOUND @@ -3055,7 +3056,7 @@ module.exports = class UserProjectsHelper { "completedDate" ]); - if ( !userProject.length > 0 ) { + if ( !(userProject.length > 0 )) { throw { status: HTTP_STATUS_CODE["bad_request"].status, message: CONSTANTS.apiResponses.PROJECT_WITH_CERTIFICATE_NOT_FOUND @@ -3139,7 +3140,7 @@ module.exports = class UserProjectsHelper { }); // if project details not found. - if (!userProject.length > 0) { + if (!(userProject.length > 0)) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.USER_PROJECT_NOT_FOUND @@ -3557,7 +3558,7 @@ function _projectCategories(categories) { _id: { $in: categoryIds } }, ["name", "externalId"]); - if (!categoryData.length > 0) { + if (!(categoryData.length > 0)) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.CATEGORY_NOT_FOUND @@ -3654,7 +3655,7 @@ function _entitiesInformation(entityIds) { } } - if ( !entityInformations.length > 0 ) { + if ( !(entityInformations.length > 0) ) { throw { status: HTTP_STATUS_CODE['bad_request'].status, message: CONSTANTS.apiResponses.ENTITY_NOT_FOUND From 391812ce2d3197d3ba42b801c981f41b2cb9f211 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Tue, 2 Apr 2024 16:35:25 +0530 Subject: [PATCH 357/373] added releasenotes for 8.0.0 --- package.json | 2 +- release-notes/8.0.0.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 release-notes/8.0.0.md diff --git a/package.json b/package.json index e6d56131..da90639c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sl-improvement-service", - "version": "7.0.0", + "version": "8.0.0", "description": "Improvement service", "main": "app.js", "bin": { diff --git a/release-notes/8.0.0.md b/release-notes/8.0.0.md new file mode 100644 index 00000000..ec37aa33 --- /dev/null +++ b/release-notes/8.0.0.md @@ -0,0 +1,19 @@ +# Release Note 8.0.0 ML Projects Service + +This version contains set of manual activites tasks that must be completed in order to improve to upgrade the ML Projects service code to 8.0.0. Please consider the following list of tasks to be completed. + +### Deploy ml-projects-services + +To retrieve the latest release tag for version 8.0.0, please visit the following URL: https://github.com/project-sunbird/ml-projects-service/tags e.g. release-8.0.0_RC1 + +To proceed with the deployment process, follow the steps below: + + 1. Log in to Jenkins. + 2. Navigate to Dashboard -> AutoBuild -> StagingManual -> managed-learn -> ml-projects-service. OR for dev Navigate to Dashboard -> Build -> managed-learn -> ml-projects-service + 3. Click on "Build with parameters" and provide the latest release tag in the field labeled "github_release_tag". Initiate the build process. + 4. The build job will take approximately 5 minutes to complete. + 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-projects-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-projects-service This job will be executed automatically in the dev environment. If not, then it should be built manually. + 6. Click on "Build with parameters" to initiate the deployment process. + 7. Once the job is completed, the services will be deployed on the staging environment + +### No New Environment Keys Added From d2ec2c9f7e2a3ca691f8dd01d598f52b6cd87fd8 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Wed, 3 Apr 2024 19:22:52 +0530 Subject: [PATCH 358/373] removed unwanted header from release note --- release-notes/8.0.0.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/release-notes/8.0.0.md b/release-notes/8.0.0.md index ec37aa33..d8581662 100644 --- a/release-notes/8.0.0.md +++ b/release-notes/8.0.0.md @@ -15,5 +15,3 @@ To proceed with the deployment process, follow the steps below: 5. After the job finishes, go to Dashboard -> Deploy -> staging -> managed-learn -> ml-projects-service. OR for dev go to Dashboard -> Deploy -> dev -> managed-learn -> ml-projects-service This job will be executed automatically in the dev environment. If not, then it should be built manually. 6. Click on "Build with parameters" to initiate the deployment process. 7. Once the job is completed, the services will be deployed on the staging environment - -### No New Environment Keys Added From ef2150b6bd6c578a44edad5bb9c65ecc8f88d615 Mon Sep 17 00:00:00 2001 From: praveenKDass Date: Tue, 16 Apr 2024 19:24:35 +0530 Subject: [PATCH 359/373] upgrade node -v from 18 to 20 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6c9d390e..250f5648 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18 +FROM node:20 WORKDIR /opt/projects From 6366e6ddbfee0e4bfa693b75349e11d401e61e75 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Thu, 20 Jun 2024 09:17:32 +0530 Subject: [PATCH 360/373] feat:listing api for pending projects --- app.js | 2 +- controllers/v1/userProjects.js | 43 +++++++++++++++++++++++++++++ databaseQueries/projects.js | 2 ++ generics/services/users.js | 1 + module/project/helper.js | 20 ++++++++++++++ module/userProjects/helper.js | 34 ++++++++++++++++++++++- module/userProjects/validator/v1.js | 8 ++++++ 7 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 module/project/helper.js diff --git a/app.js b/app.js index 30806a0d..79f3a486 100644 --- a/app.js +++ b/app.js @@ -60,7 +60,7 @@ const router = require("./routes"); //add routing router(app); - +console.log(process.env.APPLICATION_PORT,'<-----process.env.APPLICATION_PORT') //listen to given port app.listen(process.env.APPLICATION_PORT, () => { console.log("Environment : " + process.env.APPLICATION_ENV); diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 052a4f9b..173db7e6 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -8,6 +8,7 @@ // Dependencies const csv = require('csvtojson'); const userProjectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); +const projectsHelper = require(MODULES_BASE_PATH + "/userProjects/helper"); /** * UserProjects @@ -1125,5 +1126,47 @@ module.exports = class UserProjects extends Abstract { } }) } + /** + * @api {post} /improvement-project/api/v1/userProjects/certificateReIssue + * ReIssue project certificate (admin api) + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/certificateReIssue + * @apiParamExample {json} Response: + /**{ + "message": "Successfully generated project certificate", + "status": 200, + "result": { + "_id": "63446059eeffea2b819f036e" + } + } + /** + * ReIssue project certificate + * @method + * @name certificateReIssue + * @returns {JSON} Reissued details + */ + + async listPendingProjects(req) { + return new Promise(async (resolve, reject) => { + try { + let listOfProjects = await projectsHelper.details({ + user_id:req.userDetails.userInformation.userId, + type:req.query.status + }) + return resolve({ + message: 'success', + result: listOfProjects + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } }; \ No newline at end of file diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 3e7e6236..b7cc91bb 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -52,6 +52,8 @@ module.exports = class Projects { queryObject, projection ).lean(); + console.log({ queryObject, + projection},database.models.projects,'<---') return resolve(projects); } catch (error) { diff --git a/generics/services/users.js b/generics/services/users.js index 6b9473b8..f0b28ace 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -89,6 +89,7 @@ const locationSearch = function ( filterData, formatResult = false ) { bodyData["request"]["filters"] = filterData; const url = userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; + console.log(url,'url') const options = { headers : { "content-type": "application/json" diff --git a/module/project/helper.js b/module/project/helper.js new file mode 100644 index 00000000..027daa0e --- /dev/null +++ b/module/project/helper.js @@ -0,0 +1,20 @@ +/** + * name : helper.js + * author : Saish + * created-date : 19-june-2024 + * Description : Projects helper functionality. + */ + +/** + * ProjectsHelper + * @class + */ + +// Dependencies + +const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); + + + module.exports = class ProjectsHelper { + + }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c706a419..62134f14 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1256,6 +1256,7 @@ module.exports = class UserProjectsHelper { */ static detailsV2( projectId,solutionId,userId,userToken,bodyData,appName = "",appVersion = "",templateId = "" ) { + console.log({projectId,solutionId,userId,userToken,bodyData,appName,appVersion,templateId}) return new Promise(async (resolve, reject) => { try { @@ -2499,7 +2500,6 @@ module.exports = class UserProjectsHelper { static importFromLibrary(projectTemplateId, requestedData, userToken, userId, isATargetedSolution = "" ) { return new Promise(async (resolve, reject) => { try { - isATargetedSolution = UTILS.convertStringToBoolean(isATargetedSolution); let libraryProjects = @@ -3273,6 +3273,38 @@ module.exports = class UserProjectsHelper { }) } + /** + * Template details. + * @method + * @name details + * @param {String} templateId - Project template id. + * @param {String} userId - logged in user id. + * @params {String} link - solution link. + * @returns {Array} Project templates data. + */ + + static details({ + user_id, + type + }) { + return new Promise(async (resolve, reject) => { + try{ + + const projectIdQuery = { + userId: user_id, + status:type + }; + + let projects = await projectQueries.projectDocument(projectIdQuery); + console.log(projectIdQuery,projects); + resolve(projects) + }catch(error){ + console.log(error) + } + }); + } + + }; diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index 09dcbfa6..d9a7633e 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -33,6 +33,14 @@ module.exports = (req) => { req.checkBody("data").exists().withMessage("data is required"); req.checkBody("data.transactionId").exists().withMessage("transactionId is required"); req.checkBody("data.osid").exists().withMessage("osid is required"); + }, + listPendingProjects : function () { + req.checkQuery('status') + .exists() + .withMessage("The 'status' parameter is required.") + .isIn(['started','inProgress','submitted']) + .withMessage("The 'status' parameter must be either 'started' or 'inProgress' or 'submitted'"); + } } From 22e64bdd2be713925ede88ba42cb57a05a1cda07 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Fri, 21 Jun 2024 10:32:45 +0530 Subject: [PATCH 361/373] feat:apis added to list projects which are created and assigned to a user --- controllers/v1/userProjects.js | 68 +++++++++++++++++++++------- databaseQueries/projects.js | 2 +- generics/middleware/authenticator.js | 2 +- module/userProjects/helper.js | 38 ++++++++-------- 4 files changed, 74 insertions(+), 36 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 173db7e6..e598be01 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1127,33 +1127,30 @@ module.exports = class UserProjects extends Abstract { }) } /** - * @api {post} /improvement-project/api/v1/userProjects/certificateReIssue - * ReIssue project certificate (admin api) + * @api {post} /improvement-project/api/v1/userProjects/listPendingProjects + * Lists projects based on the status * @apiVersion 1.0.0 * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/certificateReIssue + * @apiSampleRequest /improvement-project/api/v1/userProjects/listPendingProjects * @apiParamExample {json} Response: - /**{ - "message": "Successfully generated project certificate", - "status": 200, - "result": { - "_id": "63446059eeffea2b819f036e" - } - } /** - * ReIssue project certificate + + /** + * Lists projects based on the status * @method - * @name certificateReIssue - * @returns {JSON} Reissued details + * @name listPendingProjects + * @returns {JSON} Project details */ async listPendingProjects(req) { return new Promise(async (resolve, reject) => { + try { let listOfProjects = await projectsHelper.details({ - user_id:req.userDetails.userInformation.userId, - type:req.query.status - }) + userId:req.userDetails.userInformation.userId, + status:req.query.status + },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted']) + return resolve({ message: 'success', result: listOfProjects @@ -1168,5 +1165,44 @@ module.exports = class UserProjects extends Abstract { } }) } + /** + * @api {post} /improvement-project/api/v1/userProjects/listCreatedProjects + * Lists projects created by the userId + * @apiVersion 1.0.0 + * @apiGroup User Projects + * @apiSampleRequest /improvement-project/api/v1/userProjects/listCreatedProjects + * @apiParamExample {json} Response: + /** + + /** + * Lists projects created by the userId + * @method + * @name listCreatedProjects + * @returns {JSON} Project details + */ + + + async listCreatedProjects(req) { + return new Promise(async (resolve, reject) => { + try { + let listOfCreatedProjects = await userProjectsHelper.details({ + createdBy:req.userDetails.userInformation.userId + },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted']) + + return resolve({ + message: 'success', + result: listOfCreatedProjects + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + }; \ No newline at end of file diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index b7cc91bb..7ec49b41 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -34,7 +34,7 @@ module.exports = class Projects { let queryObject = (filterData != "all") ? filterData : {}; let projection = {} - + console.log(fieldsArray,'fieldsArray') if (fieldsArray != "all") { fieldsArray.forEach(field => { projection[field] = 1; diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index b33e8879..4f4f7675 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -61,7 +61,7 @@ module.exports = async function (req, res, next, token = "") { return; } - let internalAccessApiPaths = ["/templates/bulkCreate"]; + let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/listPendingProjects','/userProjects/listCreatedProjects']; let performInternalAccessTokenCheck = false; await Promise.all(internalAccessApiPaths.map(async function (path) { if (req.path.includes(path)) { diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 62134f14..6c3f51d9 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -1256,7 +1256,7 @@ module.exports = class UserProjectsHelper { */ static detailsV2( projectId,solutionId,userId,userToken,bodyData,appName = "",appVersion = "",templateId = "" ) { - console.log({projectId,solutionId,userId,userToken,bodyData,appName,appVersion,templateId}) + return new Promise(async (resolve, reject) => { try { @@ -1564,7 +1564,7 @@ module.exports = class UserProjectsHelper { userToken, bodyData.submissions.observationId ); - console.log(observationDetails) + if( observationDetails.data && Object.keys(observationDetails.data).length > 0 && @@ -3273,33 +3273,35 @@ module.exports = class UserProjectsHelper { }) } - /** - * Template details. + /** + * Fetches project details based on the provided query. * @method * @name details - * @param {String} templateId - Project template id. - * @param {String} userId - logged in user id. - * @params {String} link - solution link. - * @returns {Array} Project templates data. + * @param {Object} args - Query object for fetching project details. + * @returns {Array} - A promise that resolves to an array of project details matching the query. */ - - static details({ - user_id, - type - }) { + static details(args,fields='all') { return new Promise(async (resolve, reject) => { try{ const projectIdQuery = { - userId: user_id, - status:type + ...args }; + + let fieldarray = [] + + if (fields != "all") { + fields.forEach(field => { + fieldarray.push(field) + }); + } - let projects = await projectQueries.projectDocument(projectIdQuery); - console.log(projectIdQuery,projects); + let projects = await projectQueries.projectDocument(projectIdQuery,fieldarray); + resolve(projects) }catch(error){ - console.log(error) + console.log(error) + throw new Error('Something went wrong!') } }); } From 84524c7b77bdc38de38e0f4fca3950cb4f16d38d Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Fri, 21 Jun 2024 10:39:53 +0530 Subject: [PATCH 362/373] feat:apis added to list projects which are created and assigned to a user --- app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app.js b/app.js index 79f3a486..1fc38b84 100644 --- a/app.js +++ b/app.js @@ -60,7 +60,6 @@ const router = require("./routes"); //add routing router(app); -console.log(process.env.APPLICATION_PORT,'<-----process.env.APPLICATION_PORT') //listen to given port app.listen(process.env.APPLICATION_PORT, () => { console.log("Environment : " + process.env.APPLICATION_ENV); From 12d83c23133adf4d35b557cbcf265aa998d0d8ec Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Fri, 21 Jun 2024 10:41:40 +0530 Subject: [PATCH 363/373] feat:apis added to list projects which are created and assigned to a user --- databaseQueries/projects.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 7ec49b41..511c1090 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -34,7 +34,7 @@ module.exports = class Projects { let queryObject = (filterData != "all") ? filterData : {}; let projection = {} - console.log(fieldsArray,'fieldsArray') + if (fieldsArray != "all") { fieldsArray.forEach(field => { projection[field] = 1; @@ -52,8 +52,6 @@ module.exports = class Projects { queryObject, projection ).lean(); - console.log({ queryObject, - projection},database.models.projects,'<---') return resolve(projects); } catch (error) { From 32cbd3e4dc4a891ee6972f5f36ff384652d3016e Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Fri, 21 Jun 2024 10:54:14 +0530 Subject: [PATCH 364/373] feat: resolving comments on the pr --- generics/services/users.js | 2 +- module/project/helper.js | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 module/project/helper.js diff --git a/generics/services/users.js b/generics/services/users.js index f0b28ace..66bb5a9f 100644 --- a/generics/services/users.js +++ b/generics/services/users.js @@ -89,7 +89,7 @@ const locationSearch = function ( filterData, formatResult = false ) { bodyData["request"]["filters"] = filterData; const url = userServiceUrl + CONSTANTS.endpoints.GET_LOCATION_DATA; - console.log(url,'url') + const options = { headers : { "content-type": "application/json" diff --git a/module/project/helper.js b/module/project/helper.js deleted file mode 100644 index 027daa0e..00000000 --- a/module/project/helper.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * name : helper.js - * author : Saish - * created-date : 19-june-2024 - * Description : Projects helper functionality. - */ - -/** - * ProjectsHelper - * @class - */ - -// Dependencies - -const projectQueries = require(DB_QUERY_BASE_PATH + "/projects"); - - - module.exports = class ProjectsHelper { - - }; From de744a03f19090b08348e5222659e112f0a286d9 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Fri, 21 Jun 2024 21:11:04 +0530 Subject: [PATCH 365/373] feat:changes as per pr comment --- controllers/v1/userProjects.js | 25 +++++++++++++++- databaseQueries/projects.js | 26 +++++++++++++++++ module/userProjects/helper.js | 45 +++++++++++++++++++++++++---- module/userProjects/validator/v1.js | 13 +++++++++ 4 files changed, 103 insertions(+), 6 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index e598be01..92ba2c03 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1203,6 +1203,29 @@ module.exports = class UserProjects extends Abstract { } }) } - + async listUserProjects(req) { + return new Promise(async (resolve, reject) => { + try { + let listOfCreatedProjects = await userProjectsHelper.listUserProjects({ + status:req.query.status, + userInvolvement:req.query.userInvolvement, + userId:req.userDetails.userInformation.userId, + stats:req.query.stats + }) + return resolve({ + message: 'success', + result: listOfCreatedProjects + }); + + } catch (error) { + return reject({ + status: error.status || HTTP_STATUS_CODE.internal_server_error.status, + message: error.message || HTTP_STATUS_CODE.internal_server_error.message, + errorObject: error + }); + } + }) + } + }; \ No newline at end of file diff --git a/databaseQueries/projects.js b/databaseQueries/projects.js index 511c1090..4c871d76 100644 --- a/databaseQueries/projects.js +++ b/databaseQueries/projects.js @@ -155,4 +155,30 @@ module.exports = class Projects { }) } + /** + * Get Observation document based on filtered data provided. + * @method + * @name countDocuments + * @param {Object} [findQuery = "all"] -filter data. + * @returns {Array} - Count of projects. + */ + + static countDocuments(findQuery = "all",) { + return new Promise(async (resolve, reject) => { + try { + let queryObject = {}; + if (findQuery != "all") { + queryObject = _.merge(queryObject, findQuery); + } + let countDocuments = await database.models.projects + .countDocuments(queryObject) + .lean(); + + return resolve(countDocuments); + } catch (error) { + return reject(error); + } + }); + } + }; diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6c3f51d9..6a27673f 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3280,7 +3280,7 @@ module.exports = class UserProjectsHelper { * @param {Object} args - Query object for fetching project details. * @returns {Array} - A promise that resolves to an array of project details matching the query. */ - static details(args,fields='all') { + static userProjectOverview(args,fields='all',stats) { return new Promise(async (resolve, reject) => { try{ @@ -3295,16 +3295,51 @@ module.exports = class UserProjectsHelper { fieldarray.push(field) }); } - + + if(stats == 'true') + { + let count = await projectQueries.countDocuments(projectIdQuery); + + resolve(count); + } + let projects = await projectQueries.projectDocument(projectIdQuery,fieldarray); resolve(projects) }catch(error){ - console.log(error) - throw new Error('Something went wrong!') + reject(error) } }); - } + } + static listUserProjects({userId,userInvolvement,stats}){ + + return new Promise(async (resolve, reject) => { + try{ + switch(userInvolvement) + { + case 'creator': + + let listOfCreatedProjects = await this.userProjectOverview({ + createdBy:userId + },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted'],stats) + + return resolve(listOfCreatedProjects); + case 'consumed': + let listOfProjects = await this.userProjectOverview({ + userId:userId + },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted'],stats) + + return resolve(listOfProjects); + default: + throw new Error('Invalid arguments passed.') + } + + }catch(error){ + + reject(error) + } + }); + } diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index d9a7633e..8b0bb3c4 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -41,6 +41,19 @@ module.exports = (req) => { .isIn(['started','inProgress','submitted']) .withMessage("The 'status' parameter must be either 'started' or 'inProgress' or 'submitted'"); + }, + listUserProjects:function(){ + req.checkQuery('userInvolvement') + .exists() + .withMessage("The 'userInvolvement' parameter is required.") + .isIn(['creator','consumed']) + .withMessage("The 'userInvolvement' parameter must be either 'creator' or 'consumed'"); + + req.checkQuery('stats') + .optional() + .isIn(['true','false']) + .withMessage("The 'stats' parameter must be either 'true' or 'false' "); + } } From e5748947ce1c5db2a20db901fcdf375c8d430a80 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Sat, 22 Jun 2024 14:46:33 +0530 Subject: [PATCH 366/373] feat:removed unused code and created only one route --- controllers/v1/userProjects.js | 77 ---------------------------------- 1 file changed, 77 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 92ba2c03..57480a1f 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1126,83 +1126,6 @@ module.exports = class UserProjects extends Abstract { } }) } - /** - * @api {post} /improvement-project/api/v1/userProjects/listPendingProjects - * Lists projects based on the status - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/listPendingProjects - * @apiParamExample {json} Response: - /** - - /** - * Lists projects based on the status - * @method - * @name listPendingProjects - * @returns {JSON} Project details - */ - - async listPendingProjects(req) { - return new Promise(async (resolve, reject) => { - - try { - let listOfProjects = await projectsHelper.details({ - userId:req.userDetails.userInformation.userId, - status:req.query.status - },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted']) - - return resolve({ - message: 'success', - result: listOfProjects - }); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } - /** - * @api {post} /improvement-project/api/v1/userProjects/listCreatedProjects - * Lists projects created by the userId - * @apiVersion 1.0.0 - * @apiGroup User Projects - * @apiSampleRequest /improvement-project/api/v1/userProjects/listCreatedProjects - * @apiParamExample {json} Response: - /** - - /** - * Lists projects created by the userId - * @method - * @name listCreatedProjects - * @returns {JSON} Project details - */ - - - async listCreatedProjects(req) { - return new Promise(async (resolve, reject) => { - try { - let listOfCreatedProjects = await userProjectsHelper.details({ - createdBy:req.userDetails.userInformation.userId - },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted']) - - return resolve({ - message: 'success', - result: listOfCreatedProjects - }); - - } catch (error) { - return reject({ - status: error.status || HTTP_STATUS_CODE.internal_server_error.status, - message: error.message || HTTP_STATUS_CODE.internal_server_error.message, - errorObject: error - }); - } - }) - } async listUserProjects(req) { return new Promise(async (resolve, reject) => { try { From a1dd8b0c80e685cb5b5d4bafda4882b976ed1b95 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Sat, 22 Jun 2024 15:09:16 +0530 Subject: [PATCH 367/373] feat:removed unused code --- generics/middleware/authenticator.js | 2 +- module/userProjects/validator/v1.js | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index 4f4f7675..81936801 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -61,7 +61,7 @@ module.exports = async function (req, res, next, token = "") { return; } - let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/listPendingProjects','/userProjects/listCreatedProjects']; + let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/listUserProjects']; let performInternalAccessTokenCheck = false; await Promise.all(internalAccessApiPaths.map(async function (path) { if (req.path.includes(path)) { diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index 8b0bb3c4..50e62bc0 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -34,14 +34,6 @@ module.exports = (req) => { req.checkBody("data.transactionId").exists().withMessage("transactionId is required"); req.checkBody("data.osid").exists().withMessage("osid is required"); }, - listPendingProjects : function () { - req.checkQuery('status') - .exists() - .withMessage("The 'status' parameter is required.") - .isIn(['started','inProgress','submitted']) - .withMessage("The 'status' parameter must be either 'started' or 'inProgress' or 'submitted'"); - - }, listUserProjects:function(){ req.checkQuery('userInvolvement') .exists() From e381270c34f568a6dfbd9fd3e94890bf65f34a3a Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Sat, 22 Jun 2024 15:46:59 +0530 Subject: [PATCH 368/373] feat:changes as per pr review --- controllers/v1/userProjects.js | 4 +--- module/userProjects/helper.js | 24 ++++++------------------ module/userProjects/validator/v1.js | 6 ------ 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 57480a1f..c1b828ce 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1126,12 +1126,10 @@ module.exports = class UserProjects extends Abstract { } }) } - async listUserProjects(req) { + async userProjects(req) { return new Promise(async (resolve, reject) => { try { let listOfCreatedProjects = await userProjectsHelper.listUserProjects({ - status:req.query.status, - userInvolvement:req.query.userInvolvement, userId:req.userDetails.userInformation.userId, stats:req.query.stats }) diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6a27673f..4eebf454 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3311,28 +3311,16 @@ module.exports = class UserProjectsHelper { } }); } - static listUserProjects({userId,userInvolvement,stats}){ + static listUserProjects({userId,stats}){ return new Promise(async (resolve, reject) => { try{ - switch(userInvolvement) - { - case 'creator': - - let listOfCreatedProjects = await this.userProjectOverview({ - createdBy:userId - },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted'],stats) - return resolve(listOfCreatedProjects); - case 'consumed': - let listOfProjects = await this.userProjectOverview({ - userId:userId - },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted'],stats) - - return resolve(listOfProjects); - default: - throw new Error('Invalid arguments passed.') - } + let listOfProjects = await this.userProjectOverview({ + userId:userId + },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted'],stats) + + return resolve(listOfProjects); }catch(error){ diff --git a/module/userProjects/validator/v1.js b/module/userProjects/validator/v1.js index 50e62bc0..bd20e83f 100644 --- a/module/userProjects/validator/v1.js +++ b/module/userProjects/validator/v1.js @@ -35,12 +35,6 @@ module.exports = (req) => { req.checkBody("data.osid").exists().withMessage("osid is required"); }, listUserProjects:function(){ - req.checkQuery('userInvolvement') - .exists() - .withMessage("The 'userInvolvement' parameter is required.") - .isIn(['creator','consumed']) - .withMessage("The 'userInvolvement' parameter must be either 'creator' or 'consumed'"); - req.checkQuery('stats') .optional() .isIn(['true','false']) From 822bf8119f4c7ebe4b290b550dca18422305a61d Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Sun, 23 Jun 2024 14:00:46 +0530 Subject: [PATCH 369/373] feat:minor changes --- controllers/v1/userProjects.js | 6 ++++++ module/userProjects/helper.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index c1b828ce..7b5d2834 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1129,6 +1129,12 @@ module.exports = class UserProjects extends Abstract { async userProjects(req) { return new Promise(async (resolve, reject) => { try { + + if (req.query.stats) { + //convert req.query.stats string to Boolean value + req.query.stats = UTILS.convertStringToBoolean(req.query.stats); + } + let listOfCreatedProjects = await userProjectsHelper.listUserProjects({ userId:req.userDetails.userInformation.userId, stats:req.query.stats diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 4eebf454..c1f53fb4 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3296,7 +3296,7 @@ module.exports = class UserProjectsHelper { }); } - if(stats == 'true') + if(stats == true) { let count = await projectQueries.countDocuments(projectIdQuery); From 76b44f7e4ce1c97fcabf657d8e508712852508f1 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Sun, 23 Jun 2024 21:29:45 +0530 Subject: [PATCH 370/373] feat:changes as per pr review --- controllers/v1/userProjects.js | 8 ++--- generics/middleware/authenticator.js | 2 +- module/userProjects/helper.js | 45 ++++++++++++++-------------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 7b5d2834..ad9d718c 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1130,14 +1130,14 @@ module.exports = class UserProjects extends Abstract { return new Promise(async (resolve, reject) => { try { - if (req.query.stats) { - //convert req.query.stats string to Boolean value - req.query.stats = UTILS.convertStringToBoolean(req.query.stats); + let stats = req.query.stats; + if (stats !== undefined) { + stats = UTILS.convertStringToBoolean(stats); } let listOfCreatedProjects = await userProjectsHelper.listUserProjects({ userId:req.userDetails.userInformation.userId, - stats:req.query.stats + stats:stats }) return resolve({ message: 'success', diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index 81936801..ece94508 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -61,7 +61,7 @@ module.exports = async function (req, res, next, token = "") { return; } - let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/listUserProjects']; + let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/userProjects']; let performInternalAccessTokenCheck = false; await Promise.all(internalAccessApiPaths.map(async function (path) { if (req.path.includes(path)) { diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index c1f53fb4..6767a0a8 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3282,32 +3282,33 @@ module.exports = class UserProjectsHelper { */ static userProjectOverview(args,fields='all',stats) { return new Promise(async (resolve, reject) => { - try{ - - const projectIdQuery = { - ...args - }; + try { + const projectIdQuery = { + ...args, + }; - let fieldarray = [] - - if (fields != "all") { - fields.forEach(field => { - fieldarray.push(field) - }); - } + let fieldarray = []; - if(stats == true) - { - let count = await projectQueries.countDocuments(projectIdQuery); + if (fields != "all") { + fields.forEach((field) => { + fieldarray.push(field); + }); + } - resolve(count); - } + if (stats == true) { + let count = await projectQueries.countDocuments(projectIdQuery); - let projects = await projectQueries.projectDocument(projectIdQuery,fieldarray); - - resolve(projects) - }catch(error){ - reject(error) + resolve(count); + } + + let projects = await projectQueries.projectDocument( + projectIdQuery, + fieldarray + ); + + resolve(projects); + } catch (error) { + reject(error); } }); } From 93e61ef00b0a87582beb84fa4b4ea961cdc2ced3 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Sun, 23 Jun 2024 21:32:16 +0530 Subject: [PATCH 371/373] feat:changes as per pr review --- controllers/v1/userProjects.js | 8 ++++---- module/userProjects/helper.js | 17 ----------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index ad9d718c..9d0abbc0 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1135,10 +1135,10 @@ module.exports = class UserProjects extends Abstract { stats = UTILS.convertStringToBoolean(stats); } - let listOfCreatedProjects = await userProjectsHelper.listUserProjects({ - userId:req.userDetails.userInformation.userId, - stats:stats - }) + let listOfCreatedProjects = await userProjectsHelper.userProjectOverview({ + userId:req.userDetails.userInformation.userId + },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted'],stats) + return resolve({ message: 'success', result: listOfCreatedProjects diff --git a/module/userProjects/helper.js b/module/userProjects/helper.js index 6767a0a8..57e6a852 100644 --- a/module/userProjects/helper.js +++ b/module/userProjects/helper.js @@ -3312,23 +3312,6 @@ module.exports = class UserProjectsHelper { } }); } - static listUserProjects({userId,stats}){ - - return new Promise(async (resolve, reject) => { - try{ - - let listOfProjects = await this.userProjectOverview({ - userId:userId - },['title','description','_id','userId','isAPrivateProgram','createdBy','status','createdAt','deleted'],stats) - - return resolve(listOfProjects); - - }catch(error){ - - reject(error) - } - }); - } From 411331fb2ad72ecb10dba712c6aec0a7c5c3f513 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Mon, 24 Jun 2024 10:28:44 +0530 Subject: [PATCH 372/373] feat:cosmetic change usersProject/userProject to userProject/project --- controllers/v1/userProjects.js | 2 +- generics/middleware/authenticator.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 9d0abbc0..979ccd31 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1126,7 +1126,7 @@ module.exports = class UserProjects extends Abstract { } }) } - async userProjects(req) { + async projects(req) { return new Promise(async (resolve, reject) => { try { diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index ece94508..dede2f2b 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -61,7 +61,7 @@ module.exports = async function (req, res, next, token = "") { return; } - let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/userProjects']; + let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/projects']; let performInternalAccessTokenCheck = false; await Promise.all(internalAccessApiPaths.map(async function (path) { if (req.path.includes(path)) { From 140b63072b4e50cfcaabf36ebfea8c2fc9a0d4f9 Mon Sep 17 00:00:00 2001 From: "saish.borkar" Date: Mon, 24 Jun 2024 10:45:29 +0530 Subject: [PATCH 373/373] feat:cosmetic change usersProject/userProject to userProject/overview --- controllers/v1/userProjects.js | 2 +- generics/middleware/authenticator.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/v1/userProjects.js b/controllers/v1/userProjects.js index 979ccd31..fb5c2a02 100644 --- a/controllers/v1/userProjects.js +++ b/controllers/v1/userProjects.js @@ -1126,7 +1126,7 @@ module.exports = class UserProjects extends Abstract { } }) } - async projects(req) { + async overview(req) { return new Promise(async (resolve, reject) => { try { diff --git a/generics/middleware/authenticator.js b/generics/middleware/authenticator.js index dede2f2b..c7388fc9 100644 --- a/generics/middleware/authenticator.js +++ b/generics/middleware/authenticator.js @@ -61,7 +61,7 @@ module.exports = async function (req, res, next, token = "") { return; } - let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/projects']; + let internalAccessApiPaths = ["/templates/bulkCreate",'/userProjects/overview']; let performInternalAccessTokenCheck = false; await Promise.all(internalAccessApiPaths.map(async function (path) { if (req.path.includes(path)) {