# Release v1.16.7 ## Services ### Update services * [core] [done] core service * [core] [done] main worker service * [core] [done] modules: * [done] NICE inContact * [done] rake user app worker * [core] [done] admin service * [core] [done] permissions service * [core] [done] user app worker service * [core] [done] event trigger service * [core] [not need] statistic service * [core] [inprogress] rake chat widget service * [core] [done] event notifications service ### New services * [user-app] notifications service * [user-app] billings service * [core] [done] api service * [core] [done] resource defaults service ## DB ### [done] Email aliases #### [done] systemUsers collection Script for converting existing data ``` const data = db.systemUsers.find({ email: { $exists: true } }).toArray(); const workspaces = db.workspaces.find().projection({ workspaceId: 1, workspaceStatusId: 1 }).toArray().reduce((acc, cur) => { acc[cur.workspaceId] = cur.workspaceStatusId; return acc; }, {}); data.forEach((systemUser, i) => { let result = db.workspaceSystemUsers.find({ systemUserId: systemUser.systemUserId }) .toArray().map(e => { return { id: e.workspaceId, email: (e.emails && e.emails[0]) || systemUser.email, isVerifiedEmail: systemUser.isVerifiedEmail, updatedEmail: systemUser.updatedEmail, referenceValues: { workspaceStatusId: workspaces[e.workspaceId], workspaceSystemUserStatusId: e.status } } }).reduce((acc, cur) => { acc.workspaces.push(cur); return acc; }, { systemUserId: systemUser.systemUserId, fieldName: 'workspaces', workspaces: [] }); db.systemUsers.updateOne( { systemUserId: result.systemUserId }, { $push: { [`emails.${result.fieldName}`]: { $each: result[result.fieldName] } } } ); result = db.projectSystemUsers.find({ systemUserId: systemUser.systemUserId }) .toArray().map(e => { return { id: e.projectId, email: (e.emails && e.emails[0]) || systemUser.email, isVerifiedEmail: systemUser.isVerifiedEmail, updatedEmail: systemUser.updatedEmail, } }).reduce((acc, cur) => { acc.projects.push(cur); return acc; }, { systemUserId: systemUser.systemUserId, fieldName: 'projects', projects: [] }); db.systemUsers.updateOne( { systemUserId: result.systemUserId }, { $push: { [`emails.${result.fieldName}`]: { $each: result[result.fieldName] } } } ); result = db.organizationSystemUsers.find({ systemUserId: systemUser.systemUserId }) .toArray().map(e => { return { id: e.organizationId, email: (e.emails && e.emails[0]) || systemUser.email, isVerifiedEmail: systemUser.isVerifiedEmail, updatedEmail: systemUser.updatedEmail, } }).reduce((acc, cur) => { acc.organizations.push(cur); return acc; }, { systemUserId: systemUser.systemUserId, fieldName: 'organizations', organizations: [] }); db.systemUsers.updateOne( { systemUserId: result.systemUserId }, { $push: { [`emails.${result.fieldName}`]: { $each: result[result.fieldName] } } } ); console.log(`${i} from ${data.length} systemUserId:${result.systemUserId}`) }) ``` ### [done] Reference values #### [not need] sessions collection Schema: ```=javascript { referenceValues: { workspace: { name } } } ``` Script for converting existing data ```=javascript ``` Schema: ```=javascript { entities: { referenceValues: { entity: { firstName, lastName, profile: { imageUrl, color } } } } } ``` Script for converting existing data ```=javascript ``` #### [done] systemUsers collection Schema: ```=javascript { emails: { workspaces: { referenceValues: { workspaceStatusId, workspaceSystemUserStatusId } } } } ``` #### [done] workspace/project/organizationSystemUser Schema: ```=javascript { referenceValues: { entity: { email, entityId, firstName, lastName, phoneNumber } } } ``` Script for converting existing data ```=javascript const systemUsers = db.systemUsers.aggregate([ { $lookup: { from: 'entities', localField: 'entityId', foreignField: 'entityId', as: 'entity' } }, { $unwind: '$entity' }, ]).toArray(); systemUsers.forEach((systemUser,i) => { const entity = { entityId: systemUser.entityId, firstName: systemUser.entity.firstName, lastName: systemUser.entity.lastName, phoneNumber: systemUser.entity.phoneNumber, email: systemUser.entity.email, }; [ db.workspaceSystemUsers, db.projectSystemUsers, db.organizationSystemUsers ].forEach(collection => { collection.updateOne( { systemUserId: systemUser.systemUserId }, { $set: { 'referenceValues.entity': entity } } ); console.log(`${i} from ${systemUsers.length}`); }); }) ``` #### [done] workspaces collection Schema: ```=javascript { referenceValues: { modules: { count } } } ``` Script for converting existing data ```=javascript let res = db.workspaces.aggregate([{ $lookup: { from: "workspaceModules", localField: "workspaceId", foreignField: "workspaceId", as: "workspaceModules" } }, { $project: { workspaceId: 1, count: {$size: "$workspaceModules" } } }, ]).toArray() for(let item of res) { db.workspaces.update({workspaceId: item.workspaceId}, {$set: { "referenceValues.modules.count": item.count }}) } ``` ### [done] Mongo trigger | actionId | operation name | | -------- | ---- | | 1 | replace | | 2 | insert | | 3 | update | | 4 | delete | | trigger name | description | | ------------ | ----------- | | messages_2 | Updating messageCount field in session collection | | organizationSystemUsers_2 | Put in organizationSystemUsers doc referenceValue entity: { entityId, firstName, lastName, phoneNumber, email } | projectSystemUsers_2 | Put in projectSystemUsers doc referenceValue entity: { entityId, firstName, lastName, phoneNumber, email } | workspaceSystemUsers_2_3 | Put in workspaceSystemUsers doc referenceValue entity: { entityId, firstName, lastName, phoneNumber, email }. Creating system events -142(workspace system user was created), -143(workspace system user was updated) | entities_2_3 | Creting system evnets -166(create entity), -167(update entity).<br>Updating referenceValues in workspaceSystemUser, projectSystemUser, orgnaizationSystemUser, sessions | workspaces_3 | Update reference values in session collections | workspaceModules_1_4_workspaces | Increment or decrement workspace reference value: modules.count | twilio_workspace_2_3 | Put and update field attachedToScope.count | rake_live_chat_workspace_2_3 | Put and update field attachedToScope.count | rake_direct_workspace_2_3 | Put and update field attachedToScope.count | inContact_workspace_2_3 | Put and update field attachedToScope.count | facebook_workspace_2_3 | Put and update field attachedToScope.count | entities_3 | creating system event id: -139 (system user was updated) and update referenceValues | systemUsers_2_3 | Creating uniqueIndexedEmails set of emails. Creating system event ids: -140(system user was created), -139(system user was updated) | workspaces_2_3_workspace | Creating system events ids: -137(workspace was created), -141(workspace was deactivated), -138(workspace was updated) ### [done] Roles * [done] Update field names assignments.typeId => assignments.type, scope.typeId => scope.type, ```=javascript db.roles.updateMany({}, [{ $set: { 'assignments.type': '$assignments.typeId', 'scope.type': '$scope.typeId' } }]) ``` * [done] Update general roles. Add assignments.type field ```=javascript db.roles.updateMany( { roleId: { $in: [1,2,3] }}, { $set: { 'assignments.type': 'organization' } } ) db.roles.updateMany( { roleId: { $in: [4,5,6,12] }}, { $set: { 'assignments.type': 'project' } } ) db.roles.updateMany( { roleId: { $in: [8,9,10,11] }}, { $set: { 'assignments.type': 'workspace' } } ) ``` * [done] Add new systemFunction to general roles ```=javascript const roleIds = [ 1, // Org OWner 2, // Org admin 4, // Pro Owner 5, // Pro admin 8, // Work Owner 9, // Work admin ]; db.roles.updateMany( { roleId: { $in: roleIds } }, { $push: { systemFunctionIds: { id: 591, availablePermissionTypeIds: [2, 3] } }} ) ``` * sync uat value and prod value ### systemConfig collections ``` db.systemConfigs.updateOne({ nodeEnv: 'prod' }, { $set: { 'resourceDefaults': { 'roles': { 'zapier': -1, 'agent': 12, 'organization': { 'defaultRoleIds': [ 1, 2, 3 ], 'creatorRoleId': 1 }, 'project': { 'defaultRoleIds': [ 4, 5, 6 ], 'creatorRoleId': 4 }, 'workspace': { 'defaultRoleIds': [ 8, 9, 10 ], 'creatorRoleId': 8, 'invitationIds': [ 10 ] } }, 'channels': { 'workspace': [ { 'isPublic': true, 'name': 'general', 'membershipTypeId': 2 }, { 'isPublic': true, 'name': 'external', 'membershipTypeId': 1 }, { 'isPublic': true, 'name': 'sales', 'membershipTypeId': 0 } ] }, 'platforms': { 'workspace': [ { 'platformId': 2 }, { 'platformId': 5 } ] }, 'modules': { 'workspace': [ 36 ] }, 'billings': { 'workspace': 18 }, 'businessHours': { 'workspace': { 'hours': { '1': { 'closed': false, 'opening': { 'hour': 0, 'minute': 0 }, 'closing': { 'hour': 24, 'minute': 0 } }, '2': { 'closed': false, 'opening': { 'hour': 0, 'minute': 0 }, 'closing': { 'hour': 24, 'minute': 0 } }, '3': { 'closed': false, 'opening': { 'hour': 0, 'minute': 0 }, 'closing': { 'hour': 24, 'minute': 0 } }, '4': { 'closed': false, 'opening': { 'hour': 0, 'minute': 0 }, 'closing': { 'hour': 24, 'minute': 0 } }, '5': { 'closed': false, 'opening': { 'hour': 0, 'minute': 0 }, 'closing': { 'hour': 24, 'minute': 0 } }, '6': { 'closed': false, 'opening': { 'hour': 0, 'minute': 0 }, 'closing': { 'hour': 24, 'minute': 0 } }, '7': { 'closed': false, 'opening': { 'hour': 0, 'minute': 0 }, 'closing': { 'hour': 24, 'minute': 0 } } } } } }, 'resourceDefaultsUrl': 'https://resources-default-2dfusaeaaa-uc.a.run.app', 'rakeUserApp': { 'default': { 'projectId': 34 } } } }) ``` ### [done] entityTypes collection ```json= db.getCollection("entityTypes").insert({ "entityTypeId": 11, "isMergeEligible": false, "name": "API user" }) ``` ### [done] systemFunctions collection Put all docs from UAT env ### [done] events collection ```=javascript db.getCollection("events").insert({ "systemEventId": -166, "name": "Create entity record", "systemReference": "entity.created" }) db.getCollection("events").insert({ "systemEventId": -167, "name": "Update entity record", "systemReference": "entity.updated" }) ``` ### eventTriggers collection Must be inserted eventTriggerIds: -239, -240, -238, -236, -237, 64,63,65,-32-31, -116, -115, ```=javascript db.eventTriggers.insert({ "eventIds": [ NumberInt(-132) ], "filters": [], "customFilter": "", description: "Rake user app. Event about customer was created", "actions": [ { "arguments": [ { "queueName" : "notifications", "pack" : { event: 'customer-created', entityId: "{rawMessage.entityId}", workspaceId: "{rawMessage.workspaceId}", customerEntityId: "{rawMessage.customerEntityId}" } } ], "id": NumberInt(3) } ], "eventTriggerId": NumberInt(-31), "__v": NumberInt(0) }); db.eventTriggers.insertOne({ "eventIds": [ NumberInt(-166), -167 ], "filters": [{ "filterOperatorId": 5, "filterId": -1, "arguments": [ 0, '{rawMessage.entityTypeIds}' ] }], "customFilter": "", "description": "Entity record was created", "actions": [ { "arguments": [ { "queueName": "searchCache", "pack": { "event": "setCustomer", "entityId": "{rawMessage.entityId}", "entityTypeIds": "{rawMessage.entityTypeIds}", "firstName": "{rawMessage.firstName}", "lastName": "{rawMessage.lastName}", "phoneNumber": "{rawMessage.phoneNumber}", "email": "{rawMessage.email}", "workspaceIds": "{rawMessage.scope.workspaceIds}", "projectIds": "{rawMessage.scope.workspaceIds}", "organizationIds": "{rawMessage.scope.workspaceIds}" } } ], "id": NumberInt(3) } ], "eventTriggerId": NumberInt(-32) "__v": NumberInt(0) }) ``` ### [done] entities collection #### [done] Step 1 ```=javascript db.entities.updateMany({},{ $set: { 'scope.workspaceIds': [], 'scope.projectIds': [], 'scope.organizationIds': '$organizationIds' } }) ``` #### [done] Step 2 workspaceEntities ``` let result = db.workspaceEntities.aggregate([ { $match: {workspaceId: {$exists: true }}}, { $group: { _id: { workspaceId: '$workspaceId' }, entityIds: {$push: '$entityId' } } }, { $lookup: { from: 'workspaces', localField: '_id.workspaceId', foreignField: 'workspaceId', as: 'workspace' }}, { $lookup: { from: 'projects', localField: 'workspace.projectId', foreignField: 'projectId', as: 'project' }}, ] ).toArray() for(let item of result) { db.entities.updateMany({entityId: {$in: item.entityIds}}, {$addToSet: { 'scope.workspaceIds': item._id.workspaceId, 'scope.projectIds': item.project[0].projectId, 'scope.organizationIds': item.project[0].organizationId }}) } ``` #### [done] Step 3 workspaceSystemUsers ``` let result = db.workspaceSystemUsers.aggregate([{ $match: {workspaceId: {$exists: true }, }}, { $group: { _id: { workspaceId: '$workspaceId' }, systemUserIds: {$push: '$systemUserId' } } }, { $lookup: { from: 'systemUsers', localField: 'systemUserIds', foreignField: 'systemUserId', as: 'systemUsers' }}, { $lookup: { from: 'workspaces', localField: '_id.workspaceId', foreignField: 'workspaceId', as: 'workspace' }}, { $lookup: { from: 'projects', localField: 'workspace.projectId', foreignField: 'projectId', as: 'project' }}] ) .toArray() for(let item of result) { let entityIds = item.systemUsers.map(item => item.entityId) let query = {'scope.workspaceIds': item._id.workspaceId} if(item.project[0]){ query = { ...query, 'scope.projectIds': item.project[0].projectId, 'scope.organizationIds': item.project[0].organizationId } } db.entities.updateMany({entityId: {$in: entityIds}}, {$addToSet: query}) } ``` #### [done] Step 4 projectSystemUser ``` let result = db.projectSystemUsers.aggregate([{ $match: {projectId: {$exists: true }, }}, { $group: { _id: { projectId: '$projectId' }, systemUserIds: {$push: '$systemUserId' } } }, { $lookup: { from: 'systemUsers', localField: 'systemUserIds', foreignField: 'systemUserId', as: 'systemUsers' }}, { $lookup: { from: 'projects', localField: '_id.projectId', foreignField: 'projectId', as: 'project' }}, ] ) .toArray() for(let item of result) { let entityIds = item.systemUsers.map(item => item.entityId) let query = {} if(item.project[0]){ query = { ...query, 'scope.projectIds': item.project[0].projectId, 'scope.organizationIds': item.project[0].organizationId } } if(Object.keys(query).length === 0) { continue } db.entities.updateMany({entityId: {$in: entityIds}}, {$addToSet: query}) } ``` #### [done] Step 5 organizationSystemUsers ```=javascript let result = db.organizationSystemUsers.aggregate([{ $match: {organizationId: {$exists: true }, }}, { $group: { _id: { organizationId: '$organizationId' }, systemUserIds: {$push: '$systemUserId' } } }, { $lookup: { from: 'systemUsers', localField: 'systemUserIds', foreignField: 'systemUserId', as: 'systemUsers' }} ] ) .toArray() for(let item of result) { let entityIds = item.systemUsers.map(item => item.entityId) db.entities.updateMany({entityId: {$in: entityIds}}, {$addToSet: { 'scope.organizationIds': item._id.organizationId}}) } ``` ### [done] systemApplications collection Put all docs from UAT env ### [done] facebookWorkspaces collection (Max?) ``` const result = db.facebookMessenger_Workspaces.aggregate([ { $group: { _id: { appId : "$appId" }, count: { $sum: 1 } } } ]).toArray(); let promises = []; for(let item of result) { promises.push( db.facebook_Applications.updateOne({ appId: item._id.appId }, { $set: { "attachedToScope": { type: 'workspace', count: item.count } } }) ) } try { Promise.all(promises) } catch (err){ console.log(JSON.stringify(err)) } db.facebookMessenger_Workspaces.dropIndex("appId_1_pageId_1") let data = db.facebookMessenger_Workspaces.aggregate([ { $match: { appId: { $exists: true } } }, { $lookup: { 'from': 'facebook_Applications', localField: 'appId', foreignField: 'appId', as: 'facebookApp' } } ]).toArray() for(let item of data){ let { facebookWorkspaceId, facebookApp } = item; let { facebookAppId } = facebookApp[0]; db.facebookMessenger_Workspaces.update({facebookWorkspaceId}, { $set: { facebookAppId }, $unset: { appId: '' } } }) } ``` ### [done] facebookApplication collection (Max?) ``` let result = db.facebook_Applications.aggregate({ $lookup: { from: 'facebookMessenger_Workspaces', localField: 'appId', foreignField: 'appId', as: 'workspaces' }}, { $unwind: { path: '$workspaces', preserveNullAndEmptyArrays: true } }, { $group: { _id: { appId: '$appId' }, workspaces: {$addToSet: '$workspaces.workspaceId'}, projectId: {$first: '$projectId' } } } ) .toArray(); for(let item of result) { if(item.workspaces.length > 0) { db.facebook_Applications.update({appId: item._id.appId}, { $set: { scope: { type: 'workspace', ids: item.workspaces } } } ) } else { db.facebook_Applications.update({appId: item._id.appId}, { $set: { scope: { type: 'project', ids: [item.projectId] } } } ) } } ``` ### [done] inContactWorkspaces collection (Max?) ``` const result = db.inContact_Workspaces.aggregate([ { $group: { _id: { inContactAppConfigId : "$inContactAppConfigId" }, count: { $sum: 1 } } } ]).toArray(); let promises = []; for(let item of result) { promises.push( db.inContact_AppConfigurations.updateOne({ inContactAppConfigId: item._id.inContactAppConfigId }, { $set: { "attachedToScope": { type: 'workspace', count: item.count } } }) ) } try { Promise.all(promises) } catch (err){ console.log(JSON.stringify(err)) } ``` ### [done] inContactApp collection (Max?) ``` let result = db.inContact_AppConfigurations.aggregate({ $lookup: { from: 'inContact_Workspaces', localField: 'inContactAppConfigId', foreignField: 'inContactAppConfigId', as: 'workspaces' }}, { $unwind: { path: '$workspaces', preserveNullAndEmptyArrays: true } }, { $group: { _id: { inContactAppConfigId: '$inContactAppConfigId' }, workspaces: {$addToSet: '$workspaces.workspaceId'}, projectId: {$first: '$projectId' } } } ) .toArray(); for(let item of result) { if(item.workspaces.length > 0) { db.inContact_AppConfigurations.update({inContactAppConfigId: item._id.inContactAppConfigId}, { $set: { scope: { type: 'workspace', ids: item.workspaces } } } ) } else { db.inContact_AppConfigurations.update({inContactAppConfigId: item._id.inContactAppConfigId}, { $set: { scope: { type: 'project', ids: [item.projectId] } } } ) } } ``` ### [done] Rake direct collection(Max?) ``` const result = db.rakeDirect_Workspaces.aggregate([ { $group: { _id: { rakeDirectConfigurationId : "$rakeDirectConfigurationId" }, count: { $sum: 1 } } } ]).toArray(); let promises = []; for(let item of result) { promises.push( db.rakeDirect_Configurations.updateOne({ rakeDirectConfigurationId: item._id.rakeDirectConfigurationId }, { $set: { "attachedToScope": { type: 'workspace', count: item.count } } }) ) } try { Promise.all(promises) } catch (err){ console.log(JSON.stringify(err)) } ``` ### [done] Rake Direct config collection(Max?) ``` let result = db.rakeDirect_Configurations.aggregate({ $lookup: { from: 'rakeDirect_Workspaces', localField: 'rakeDirectConfigurationId', foreignField: 'rakeDirectConfigurationId', as: 'workspaces' }}, { $unwind: { path: '$workspaces', preserveNullAndEmptyArrays: true } }, { $group: { _id: { rakeDirectConfigurationId: '$rakeDirectConfigurationId' }, workspaces: {$addToSet: '$workspaces.workspaceId'}, projectId: {$first: '$projectId' } } } ) .toArray(); for(let item of result) { if(item.workspaces.length > 0) { db.rakeDirect_Configurations.update({rakeDirectConfigurationId: item._id.rakeDirectConfigurationId}, { $set: { scope: { type: 'workspace', ids: item.workspaces } } } ) } else { db.rakeDirect_Configurations.update({rakeDirectConfigurationId: item._id.rakeDirectConfigurationId}, { $set: { scope: { type: 'project', ids: [item.projectId] } } } ) } } ``` ### [done] Rake live chat collection(Max?) ``` const result = db.rakeLiveChat_Workspaces.aggregate([ { $group: { _id: { rakeLiveChatConfigId : "$rakeLiveChatConfigId" }, count: { $sum: 1 } } } ]).toArray(); let promises = []; for(let item of result) { promises.push( db.rakeLiveChat_Configurations.updateOne({ rakeLiveChatConfigId: item._id.rakeLiveChatConfigId }, { $set: { "attachedToScope": { type: 'workspace', count: item.count } } }) ) } try { Promise.all(promises) } catch (err){ console.log(JSON.stringify(err)) } ``` ### [done] Rake Live chat config colletion (Max?) ``` let result = db.rakeLiveChat_Configurations.aggregate({ $lookup: { from: 'rakeLiveChat_Workspaces', localField: 'rakeLiveChatConfigId', foreignField: 'rakeLiveChatConfigId', as: 'workspaces' }}, { $unwind: { path: '$workspaces', preserveNullAndEmptyArrays: true } }, { $group: { _id: { rakeLiveChatConfigId: '$rakeLiveChatConfigId' }, workspaces: {$addToSet: '$workspaces.workspaceId'}, projectId: {$first: '$projectId' } } } ) .toArray(); for(let item of result) { if(item.workspaces.length > 0) { db.rakeLiveChat_Configurations.update({rakeLiveChatConfigId: item._id.rakeLiveChatConfigId}, { $set: { scope: { type: 'workspace', ids: item.workspaces } } } ) } else { db.rakeLiveChat_Configurations.update({rakeLiveChatConfigId: item._id.rakeLiveChatConfigId}, { $set: { scope: { type: 'project', ids: [item.projectId] } } } ) } } ``` ### [done] Twilio collection(Max?) ``` const result = db.twilioSMS_Workspaces.aggregate([ { $group: { _id: { twilioProjectId : "$twilioProjectId" }, count: { $sum: 1 } } } ]).toArray(); let promises = []; for(let item of result) { promises.push( db.twilio_Projects.updateOne({ twilioProjectId: item._id.twilioProjectId }, { $set: { "attachedToScope": { type: 'workspace', count: item.count } } }) ) } try { Promise.all(promises) } catch (err){ console.log(JSON.stringify(err)) } ``` ### [done] Twilio Projects collection(Max?) ``` let result = db.twilio_Projects.aggregate({ $lookup: { from: 'twilioSMS_Workspaces', localField: 'twilioProjectId', foreignField: 'twilioProjectId', as: 'workspaces' }}, { $unwind: { path: '$workspaces', preserveNullAndEmptyArrays: true } }, { $group: { _id: { twilioProjectId: '$twilioProjectId' }, workspaces: {$addToSet: '$workspaces.workspaceId'}, projectId: {$first: '$projectId' } } } ) .toArray(); for(let item of result) { if(item.workspaces.length > 0) { db.twilio_Projects.update({twilioProjectId: item._id.twilioProjectId}, { $set: { scope: { type: 'workspace', ids: item.workspaces } } } ) } else { db.twilio_Projects.update({twilioProjectId: item._id.twilioProjectId}, { $set: { scope: { type: 'project', ids: [item.projectId] } } } ) } } ``` ### [done] projects collection (Max?) ``` const projects = db.projects.find({}).toArray() projects.forEach(item => { if(item.settings && item.settings.languageCode) { db.projects.update( {projectId: item.projectId}, {$set: { languageCode: item.settings.languageCode }, $unset: { settings: "" } }) } }) projects.forEach(item => { if(item.settings && item.settings.language) { db.projects.update( {projectId: item.projectId}, {$set: { languageCode: item.settings.language }, $unset: { settings: "" } }) } }) ``` ### [done] organizations collection (Max?) ``` const organizations = db.organizations.find({}).toArray() organizations.forEach(item => { if(item.settings && item.settings.languageCode) { db.organizations.update( {organizationId: item.organizationId}, {$set: { languageCode: item.settings.languageCode }, $unset: { settings: "" } }) } }) ``` ### [done] Zapier Workspaces(Max?) ``` db.getCollection("zapier_Workspaces").update({}, { $set: { "isEnabled": NumberInt(1) } }, {multi: true}) ``` ## [done] Dynamic links updates Run it from dynamic-links.js - admin service ``` const createDynamicLinksScript = async () => { const invitations = await Invitations.find({ shortLink: { $exists: false }, 'scope.type': 'workspace', invitationTypeId: 1, }).select(['token', 'scope', 'invitationId']).lean(); invitations.forEach(async (invitation) => { const { shortLink } = await getDynamicLink({ link: module.exports.generateLinks.workspace .inviteByLink(invitation.scope.id, invitation.token), }); Invitation.findOneAndUpdate({ invitationId: invitation.invitationId, }, { $set: { shortLink, }, }); }); }; ``` ## [in progress] Presence updates Fields for renaming > subscribedAt --- > *createdAt* > unsubscribedAt --- > *deletedAt* Fields for removing > systemUserPresenceId > workspaceId ```=javascript const systemUserPresences = db.systemUserPresences.find({}); db.systemUserPresences.dropIndex("systemUserPresenceId_1"); db.systemUserPresences.dropIndex("unsubscribedAt_1"); db.systemUserPresences.dropIndex("entityId_1_workspaceId_1_unsubscribedAt_1_pubnubConnectionType_1"); db.systemUserPresences.dropIndex("systemUserId_1_workspaceId_1_unsubscribedAt_1_pubnubConnectionType_1"); db.systemUserPresences.dropIndex("pubnubConnectionType_1"); db.systemUserPresences.dropIndex("entityId_1_workspaceId_1_unsubscribedAt_1_connectionType_1"); db.systemUserPresences.dropIndex("entityId_1_unsubscribedAt_1"); systemUserPresences.forEach((presence) => { db.systemUserPresences.update({ _id: ObjectId(presence._id) }, { $unset: { workspaceId: 1, systemUserPresenceId: 1 } }, false, true); db.systemUserPresences.update({ _id: ObjectId(presence._id) }, { $rename: { subscribedAt: 'createdAt', unsubscribedAt: 'deletedAt', } }); console.log('presence updated: ' + presence._id); }); db.getCollection("systemUserPresences").createIndex({ "deletedAt": 1 }, { expireAfterSeconds: 172800, partialFilterExpression: { connectionType: { $eq: 'web' }, deletedAt: { $exists: true }, }, }); db.getCollection("systemUserPresences").createIndex({ "entityId": 1, deletedAt: 1, connectionType: 1 }); db.getCollection("systemUserPresences").createIndex({ "entityId": 1, deletedAt: 1 }); ``` ## [done] Channels updates ### Default channels ```=javascript const membershipTypes = { standard: 0, default: 1, locked: 2, }; const sessionsWithDefaultChannels = db.sessions.find({ channel: { $exists: true }, 'channel.isDefault': true }); sessionsWithDefaultChannels.forEach((session) => { const update = { "isDirect" : session.channel.isDirect, "_id" : session.channel._id, "entityId" : session.channel.entityId, "isPublic" : session.channel.isPublic, "channelId" : session.channel.channelId, "name" : session.channel.name, membershipTypeId: membershipTypes.locked, }; db.sessions.updateOne({ sessionId: session.sessionId }, { $set: { channel: update, }, }); console.log('session updated: ' + session.sessionId); }); ``` ### Standard channels ``` const membershipTypes = { standard: 0, default: 1, locked: 2, }; const sessionsChannels = db.sessions.find({ channel: { $exists: true }, 'channel.isDefault': false }); sessionsChannels.forEach((session) => { const update = { "isDirect" : session.channel.isDirect, "_id" : session.channel._id, "entityId" : session.channel.entityId, "isPublic" : session.channel.isPublic, "channelId" : session.channel.channelId, "name" : session.channel.name, membershipTypeId: membershipTypes.standard, }; db.sessions.updateOne({ sessionId: session.sessionId }, { $set: { channel: update, }, }); console.log('session updated: ' + session.sessionId); }); ``` ### Assign owner and creator ``` const sessionsChannels = db.sessions.find({ channel: { $exists: true } }); sessionsChannels.forEach((session) => { const entities = session.entities.filter(one => !one.isInitiator).sort((a, b) => a.entityId - b.entityId); if (!entities.length) { console.log('No other but initator found in sessionId: ' + session.sessionId); } const [owner] = entities; db.sessions.updateOne({ sessionId: session.sessionId }, { $set: { channel: { ...session.channel, ownerEntityId: owner.entityId, creatorEntityId: owner.entityId, }, }, }); console.log('session updated: ' + session.sessionId); }); ``` ## Last steps ### Clean up collections ``` db.appDevices.drop() db.billingPlanFeatureRates.drop() db.billingInvoices.drop() db.billingPaymentQueue.drop() db.billingPlanFeatureAddOns.drop() db.billingPlanWorkspaces.drop() db.billingProcessLogs.drop() db.billingTransactionsInvoices.drop() db.billingTypes.drop() db.billingWorkspaceCredits.drop() db.conversationStatuses.drop() db.customers.drop() db.organizationSettings.drop() db.phoneTypes.drop() db.platformPreconfiguredAssets.drop() db.projectSettings.drop() db.roleSystemPermissions.drop() db.services.drop() db.sessionEntities.drop() db.systemUserContacts.drop() db.systemUserRoles.drop() db.systemUserSettings.drop() db.systemUserStatuses.drop() db.teamSystemUsers.drop() db.tutorialItems.drop() db.tutorialItemRoles.drop() db.tutorialItemSystemUsers.drop() db.workspaceEntities.drop() db.workspacePaymentTransactions.drop() db.workspaceSettings.drop() ``` ### User profiles regenarate user profiles by permissions cache route ### other steps ``` db.twilio_Projects.dropIndex("accountSid_1") db.twilio_Projects.dropIndex("projectId_1_accountSid_1"); db.twilio_Projects.createIndex( { projectId: 1, accountSid: 1 }, { name: "projectId_1_accountSid_1", background: true } ) db.getCollection("twilio_Projects").createIndex( { "accountSid": 1, "scope.ids": 1, "scope.type": 1 }, { name: 'UniqueConfiguration', unique: true, partialFilterExpression: { "scope": { $exists: true } } } ) db.rakeLiveChat_Configurations.dropIndex("configurationName_1_projectId_1") db.facebook_Applications.updateMany({}, { $unset: { projectId: 1 } }); db.inContact_AppConfigurations.updateMany({}, { $unset: { projectId: 1 } }); db.rakeDirect_Configurations.updateMany({}, { $unset: { projectId: 1 } }); db.rakeLiveChat_Configurations.updateMany({}, { $unset: { projectId: 1 } }); db.twilio_Projects.updateMany({}, { $unset: { projectId: 1 } }); ```