diff --git a/migrations/challenges/sync-all-challenges.js b/migrations/challenges/sync-all-challenges.js new file mode 100644 index 0000000000..5200bab806 --- /dev/null +++ b/migrations/challenges/sync-all-challenges.js @@ -0,0 +1,47 @@ +import Bluebird from 'Bluebird'; + +import { model as Challenges } from '../../website/server/models/challenge'; +import { model as User } from '../../website/server/models/user'; + +async function syncChallengeToMembers (challenges) { + let challengSyncPromises = challenges.map(async function (challenge) { + let users = await User.find({ + // _id: '', + challenges: challenge._id, + }).exec(); + + let promises = []; + users.forEach(function (user) { + promises.push(challenge.syncToUser(user)); + promises.push(challenge.save()); + promises.push(user.save()); + }); + + return Bluebird.all(promises); + }); + + return await Bluebird.all(challengSyncPromises); +} + +async function syncChallenges (lastChallengeDate) { + let query = { + // _id: '', + }; + + if (lastChallengeDate) { + query.createdOn = { $lte: lastChallengeDate }; + } + + let challengesFound = await Challenges.find(query) + .limit(10) + .sort('-createdAt') + .exec(); + + let syncedChallenges = await syncChallengeToMembers(challengesFound) + .catch(reason => console.error(reason)); + let lastChallenge = challengesFound[challengesFound.length - 1]; + if (lastChallenge) syncChallenges(lastChallenge.createdAt); + return syncedChallenges; +}; + +module.exports = syncChallenges; diff --git a/migrations/migration-runner.js b/migrations/migration-runner.js index 33b6d35279..f767f60105 100644 --- a/migrations/migration-runner.js +++ b/migrations/migration-runner.js @@ -1,24 +1,25 @@ -require("babel-register"); -require("babel-polyfill"); - -// This file must use ES5, everything required can be in ES6 - -function setUpServer () { - var nconf = require('nconf'); - var mongoose = require('mongoose'); - var Bluebird = require('bluebird'); - var setupNconf = require('../website/server/libs/setupNconf'); - setupNconf(); - // We require src/server and npt src/index because - // 1. nconf is already setup - // 2. we don't need clustering - require('../website/server/server'); // eslint-disable-line global-require -} -setUpServer(); - -// Replace this with your migration -var processUsers = require('./groups/update-groups-with-group-plans'); -processUsers() - .catch(function (err) { - console.log(err) - }) +require("babel-register"); +require("babel-polyfill"); + +// This file must use ES5, everything required can be in ES6 + +function setUpServer () { + var nconf = require('nconf'); + var mongoose = require('mongoose'); + var Bluebird = require('bluebird'); + var setupNconf = require('../website/server/libs/setupNconf'); + setupNconf(); + // We require src/server and npt src/index because + // 1. nconf is already setup + // 2. we don't need clustering + require('../website/server/server'); // eslint-disable-line global-require +} +setUpServer(); + +// Replace this with your migration +var processUsers = require('./groups/update-groups-with-group-plans'); +processUsers() + .catch(function (err) { + console.log(err) + }) + diff --git a/test/api/v3/unit/models/challenge.test.js b/test/api/v3/unit/models/challenge.test.js index bbde1064a7..49f0ce9283 100644 --- a/test/api/v3/unit/models/challenge.test.js +++ b/test/api/v3/unit/models/challenge.test.js @@ -104,6 +104,40 @@ describe('Challenge Model', () => { expect(updatedNewMember.tags[7].id).to.equal(challenge._id); expect(updatedNewMember.tags[7].name).to.equal(challenge.shortName); expect(syncedTask).to.exist; + expect(syncedTask.attribute).to.eql('str'); + }); + + it('syncs a challenge to a user with the existing task', async () => { + await challenge.addTasks([task]); + + let updatedLeader = await User.findOne({_id: leader._id}); + let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}}); + let syncedTask = find(updatedLeadersTasks, function findNewTask (updatedLeadersTask) { + return updatedLeadersTask.challenge.taskId === task._id; + }); + + let createdAtBefore = syncedTask.createdAt; + let attributeBefore = syncedTask.attribute; + + let newTitle = 'newName'; + task.text = newTitle; + task.attribute = 'int'; + await task.save(); + await challenge.syncToUser(leader); + + updatedLeader = await User.findOne({_id: leader._id}); + updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}}); + + syncedTask = find(updatedLeadersTasks, function findNewTask (updatedLeadersTask) { + return updatedLeadersTask.challenge.taskId === task._id; + }); + + let createdAtAfter = syncedTask.createdAt; + let attributeAfter = syncedTask.attribute; + + expect(createdAtBefore).to.eql(createdAtAfter); + expect(attributeBefore).to.eql(attributeAfter); + expect(syncedTask.text).to.eql(newTitle); }); it('updates tasks to challenge and challenge members', async () => { diff --git a/website/server/libs/taskManager.js b/website/server/libs/taskManager.js index 2a47207384..163dbc452c 100644 --- a/website/server/libs/taskManager.js +++ b/website/server/libs/taskManager.js @@ -184,7 +184,7 @@ export async function getTasks (req, res, options = {}) { export function syncableAttrs (task) { let t = task.toObject(); // lodash doesn't seem to like _.omit on Document // only sync/compare important attrs - let omitAttrs = ['_id', 'userId', 'challenge', 'history', 'tags', 'completed', 'streak', 'notes', 'updatedAt', 'group', 'checklist']; + let omitAttrs = ['_id', 'userId', 'challenge', 'history', 'tags', 'completed', 'streak', 'notes', 'updatedAt', 'createdAt', 'group', 'checklist', 'attribute']; if (t.type !== 'reward') omitAttrs.push('value'); return _.omit(t, omitAttrs); }