Subject: Built motion from commit d5a4280.|0.0.141
From: Daniele Cinti <[email-masked]>
Date: Tue, 13 Sep 2016 13:00:14 +0000 (+0200)

Built motion from commit d5a4280.|0.0.141
---

diff --git a/release-notes/changelog_0.0.141.txt b/release-notes/changelog_0.0.141.txt
index e580313..bac1ae5 100644
--- a/release-notes/changelog_0.0.141.txt
+++ b/release-notes/changelog_0.0.141.txt
@@ -1,5 +1,12 @@
 # xCALLY MOTION Changelog
 
+- * 0cbc254 - 2016-09-13: server side models interval + user 
+- * 0c84ddb - 2016-09-13: sever side update tools + app.js 
+- * f8ce2ee - 2016-09-13: automation chat update (server side - emitter) 
+- * 7a3e5af - 2016-09-13: automation fax update (server side - emitter) automation mail update (server side - code clean) 
+- * e49ba5d - 2016-09-13: automation mail update (server side - emitter) 
+- * 22e90bb - 2016-09-13: Log removed 
+- * 4b2abca - 2016-09-13: Added cluster emitter to agi service 
 - * 5daed3e - 2016-09-13: server side model cluster emitter 
 - * 448ae9a - 2016-09-13: server side config/ami update cluster emitter 
 - * a7fe2de - 2016-09-13: server side config/ami update 
diff --git a/server/app.js b/server/app.js
index 980ee0d..eda90e8 100644
--- a/server/app.js
+++ b/server/app.js
@@ -67,9 +67,9 @@ if (!sticky.listen(server, config.port)) {
       }
 
       // Start Cally Square Projects
-      require('./config/automations/mail')(); // andre
-      require('./config/automations/fax')(); // andre
-      require('./config/automations/chat')(); // andre
+      require('./config/automations/mail')();
+      require('./config/automations/fax')();
+      require('./config/automations/chat')();
       require('./config/triggers')(ami); // max
       require('./config/ami')(ami); // dani
       require('./config/scheduler')(); // max
diff --git a/server/config/agi/index.js b/server/config/agi/index.js
index fb93ce6..4f1d0dd 100644
--- a/server/config/agi/index.js
+++ b/server/config/agi/index.js
@@ -1,6 +1,7 @@
 var cp = require('child_process');
 var util = require('util');
 var models = require('../../models');
+var emitter = require('cluster-emitter');
 
 module.exports = function() {
   var child = cp
@@ -74,7 +75,7 @@ module.exports = function() {
 
 function synchCollection(data, child) {
   var condition = {};
-  models[data.model].afterCreate(function(doc) {
+  emitter.on(data.model + '.afterCreate', function(doc) {
     condition[data.key] = doc[data.key];
     child.send({
       message: 'updateCollection',
@@ -83,7 +84,7 @@ function synchCollection(data, child) {
       doc: doc
     });
   });
-  models[data.model].afterUpdate(function(doc) {
+  emitter.on(data.model + '.afterUpdate', function(doc) {
     condition[data.key] = doc[data.key];
     child.send({
       message: 'updateCollection',
@@ -92,7 +93,7 @@ function synchCollection(data, child) {
       doc: doc
     });
   });
-  models[data.model].afterDestroy(function(doc) {
+  emitter.on(data.model + '.afterDestroy', function(doc) {
     condition[data.key] = doc[data.key];
     child.send({
       message: 'removeFromCollection',
@@ -102,19 +103,60 @@ function synchCollection(data, child) {
   });
 }
 
+// function synchCollection(data, child) {
+//   var condition = {};
+//   models[data.model].afterCreate(function(doc) {
+//     condition[data.key] = doc[data.key];
+//     child.send({
+//       message: 'updateCollection',
+//       collection: data.collection,
+//       condition: condition,
+//       doc: doc
+//     });
+//   });
+//   models[data.model].afterUpdate(function(doc) {
+//     condition[data.key] = doc[data.key];
+//     child.send({
+//       message: 'updateCollection',
+//       collection: data.collection,
+//       condition: condition,
+//       doc: doc
+//     });
+//   });
+//   models[data.model].afterDestroy(function(doc) {
+//     condition[data.key] = doc[data.key];
+//     child.send({
+//       message: 'removeFromCollection',
+//       collection: data.collection,
+//       condition: condition
+//     });
+//   });
+// }
+
 function replaceCollection(data, child) {
-  var condition = {};
-  models[data.model].afterCreate(function(doc) {
+  emitter.on(data.model + '.afterCreate', function(doc) {
     getCollection(data, child, doc);
   });
-  models[data.model].afterUpdate(function(doc) {
+  emitter.on(data.model + '.afterUpdate', function(doc) {
     getCollection(data, child, doc);
   });
-  models[data.model].afterDestroy(function(doc) {
+  emitter.on(data.model + '.afterDestroy', function(doc) {
     getCollection(data, child, doc);
   });
 }
 
+// function replaceCollection(data, child) {
+//   models[data.model].afterCreate(function(doc) {
+//     getCollection(data, child, doc);
+//   });
+//   models[data.model].afterUpdate(function(doc) {
+//     getCollection(data, child, doc);
+//   });
+//   models[data.model].afterDestroy(function(doc) {
+//     getCollection(data, child, doc);
+//   });
+// }
+
 function getCollection(data, child, doc) {
   models[data.model]
     .findAll()
diff --git a/server/config/automations/chat.js b/server/config/automations/chat.js
index bf45b45..dadde96 100644
--- a/server/config/automations/chat.js
+++ b/server/config/automations/chat.js
@@ -2,14 +2,14 @@
 
 var _ = require('lodash');
 var moment = require('moment');
+var emitter = require('cluster-emitter');
 
 var Automation = require('../../models').Automation;
 var ChatRoom = require('../../models').ChatRoom;
-var automationTimeout;
 var activeChatAutomations = {};
 
 function executeAutomation(id) {
-  console.log('Executing Chat Automation ', id);
+  console.log('[Automation] Executing Chat', id);
   var _chatAutomation;
   return Automation
     .scope('all')
@@ -52,7 +52,9 @@ function executeAutomation(id) {
       });
     })
     .catch(function(err) {
-      console.log('Chat Automation exec error', err);
+      console.error('[Automation] Error in Chat exec');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 }
 
@@ -65,7 +67,9 @@ function setStatus(ticketId, newStatus) {
       }
     })
     .catch(function(err) {
-      console.log('Automatic chat status error', err);
+      console.error('[Automation] Error in Mail setStatus');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 }
 
@@ -117,7 +121,7 @@ function getCondition(condition) {
 }
 
 function createInterval(chatAutomation) {
-  console.log('Chat Automation ', chatAutomation.id, ' set with timeout ', chatAutomation.timeout * 60 * 1000);
+  console.log('[Automation] Mail', chatAutomation.id, 'set with timeout', chatAutomation.timeout * 60 * 1000);
   activeChatAutomations['interval' + chatAutomation.id] = setInterval(function() {
     executeAutomation(chatAutomation.id);
   }, chatAutomation.timeout * 60 * 1000);
@@ -125,31 +129,39 @@ function createInterval(chatAutomation) {
 
 module.exports = function() {
 
-  Automation.afterCreate(function(doc, options) {
-    console.log('Chat Automation ', doc.id, ' created, the status is ', doc.status);
-    if (doc.status && doc.channel === 'chat') {
-      createInterval(doc);
+  console.log('[Automation] Chat service started');
+
+  emitter.on('Automation.afterCreate', function(doc, options) {
+    if (doc.channel === 'chat') {
+      console.log('[Automation] Chat', doc.id, 'created, the status is', doc.status);
+      if (doc.status) {
+        createInterval(doc);
+      }
     }
   });
 
-  Automation.afterUpdate(function(doc, options) {
-    console.log('Chat Automation ', doc.id, ' updated, the status is ', doc.status);
-    if (activeChatAutomations['interval' + doc.id]) {
-      console.log('Chat automation unset ', doc.id);
-      clearInterval(activeChatAutomations['interval' + doc.id]);
-      delete activeChatAutomations['interval' + doc.id];
-    }
-    if (doc.status && doc.channel === 'chat') {
-      createInterval(doc);
+  emitter.on('Automation.afterUpdate', function(doc, options) {
+    if (doc.channel === 'chat') {
+      console.log('[Automation] Chat', doc.id, 'updated, the status is', doc.status);
+      if (activeChatAutomations['interval' + doc.id]) {
+        console.log('[Automation] Chat unset ', doc.id);
+        clearInterval(activeChatAutomations['interval' + doc.id]);
+        delete activeChatAutomations['interval' + doc.id];
+      }
+      if (doc.status) {
+        createInterval(doc);
+      }
     }
   });
 
-  Automation.afterDelete(function(doc, options) {
-    console.log('Chat Automation ', doc.id, ' deleted');
-    if (activeChatAutomations['interval' + doc.id]) {
-      console.log('Chat automation unset ', doc.id);
-      clearInterval(activeChatAutomations['interval' + doc.id]);
-      delete activeChatAutomations['interval' + doc.id];
+  emitter.on('Automation.afterDelete', function(doc, options) {
+    if (doc.channel === 'chat') {
+      console.log('[Automation] Chat', doc.id, ' deleted');
+      if (activeChatAutomations['interval' + doc.id]) {
+        console.log('[Automation] Chat unset ', doc.id);
+        clearInterval(activeChatAutomations['interval' + doc.id]);
+        delete activeChatAutomations['interval' + doc.id];
+      }
     }
   });
 
@@ -164,11 +176,16 @@ module.exports = function() {
     })
     .then(function(chatAutomations) {
 
+      console.log('[Automation] Chat are', chatAutomations.length);
+
       chatAutomations.forEach(function(chatAutomation) {
         createInterval(chatAutomation);
       });
+
     })
     .catch(function(err) {
-      console.log('Chat Automation init error', err);
+      console.error('[Automation] Error in Chat init');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 };
diff --git a/server/config/automations/fax.js b/server/config/automations/fax.js
index e7f0b74..6606ffa 100644
--- a/server/config/automations/fax.js
+++ b/server/config/automations/fax.js
@@ -1,18 +1,15 @@
 'use strict';
 
 var _ = require('lodash');
-var config = require('../environment');
 var moment = require('moment');
-// var stringifyObject = require('stringify-object');
+var emitter = require('cluster-emitter');
 
-var sequelize = require('../../models').sequelize;
 var Automation = require('../../models').Automation;
 var FaxRoom = require('../../models').FaxRoom;
-var automationTimeout;
 var activeFaxAutomations = {};
 
 function executeAutomation(id) {
-  console.log('Executing Mail Automation ', id);
+  console.log('[Automation] Executing Fax', id);
   var _faxAutomation;
   return Automation
     .scope('all')
@@ -56,7 +53,9 @@ function executeAutomation(id) {
       });
     })
     .catch(function(err) {
-      console.log('Fax Automation exec error', err);
+      console.error('[Automation] Error in Fax exec');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 }
 
@@ -69,7 +68,9 @@ function setStatus(ticketId, newStatus) {
       }
     })
     .catch(function(err) {
-      console.log('Automatic mail status error', err);
+      console.error('[Automation] Error in Fax setStatus');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 }
 
@@ -121,7 +122,7 @@ function getCondition(condition) {
 }
 
 function createInterval(faxAutomation) {
-  console.log('Fax Automation ', faxAutomation.id, ' set with timeout ', faxAutomation.timeout * 60 * 1000);
+  console.log('[Automation] Mail', faxAutomation.id, 'set with timeout', faxAutomation.timeout * 60 * 1000);
   activeFaxAutomations['interval' + faxAutomation.id] = setInterval(function() {
     executeAutomation(faxAutomation.id);
   }, faxAutomation.timeout * 60 * 1000);
@@ -129,31 +130,39 @@ function createInterval(faxAutomation) {
 
 module.exports = function() {
 
-  Automation.afterCreate(function(doc, options) {
-    console.log('Fax Automation ', doc.id, ' created, the status is ', doc.status);
-    if (doc.status && doc.channel === 'fax') {
-      createInterval(doc);
+  console.log('[Automation] Fax service started');
+
+  emitter.on('Automation.afterCreate', function(doc, options) {
+    if (doc.channel === 'fax') {
+      console.log('[Automation] Fax', doc.id, 'created, the status is', doc.status);
+      if (doc.status) {
+        createInterval(doc);
+      }
     }
   });
 
-  Automation.afterUpdate(function(doc, options) {
-    console.log('Fax Automation ', doc.id, ' updated, the status is ', doc.status);
-    if (activeFaxAutomations['interval' + doc.id]) {
-      console.log('Fax automation unset ', doc.id);
-      clearInterval(activeFaxAutomations['interval' + doc.id]);
-      delete activeFaxAutomations['interval' + doc.id];
-    }
-    if (doc.status && doc.channel === 'fax') {
-      createInterval(doc);
+  emitter.on('Automation.afterUpdate', function(doc, options) {
+    if (doc.channel === 'fax') {
+      console.log('[Automation] Fax', doc.id, 'updated, the status is', doc.status);
+      if (activeFaxAutomations['interval' + doc.id]) {
+        console.log('[Automation] Fax unset ', doc.id);
+        clearInterval(activeFaxAutomations['interval' + doc.id]);
+        delete activeFaxAutomations['interval' + doc.id];
+      }
+      if (doc.status) {
+        createInterval(doc);
+      }
     }
   });
 
-  Automation.afterDelete(function(doc, options) {
-    console.log('Fax Automation ', doc.id, ' deleted');
-    if (activeFaxAutomations['interval' + doc.id]) {
-      console.log('Fax automation unset ', doc.id);
-      clearInterval(activeFaxAutomations['interval' + doc.id]);
-      delete activeFaxAutomations['interval' + doc.id];
+  emitter.on('Automation.afterDelete', function(doc, options) {
+    if (doc.channel === 'fax') {
+      console.log('[Automation] Fax', doc.id, ' deleted');
+      if (activeFaxAutomations['interval' + doc.id]) {
+        console.log('[Automation] Fax unset ', doc.id);
+        clearInterval(activeFaxAutomations['interval' + doc.id]);
+        delete activeFaxAutomations['interval' + doc.id];
+      }
     }
   });
 
@@ -168,11 +177,16 @@ module.exports = function() {
     })
     .then(function(faxAutomations) {
 
+      console.log('[Automation] Fax are', faxAutomations.length);
+
       faxAutomations.forEach(function(faxAutomation) {
         createInterval(faxAutomation);
       });
+
     })
     .catch(function(err) {
-      console.log('Fax Automation init error', err);
+      console.error('[Automation] Error in Mail init');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 };
diff --git a/server/config/automations/mail.js b/server/config/automations/mail.js
index 14f8d17..cd4d174 100644
--- a/server/config/automations/mail.js
+++ b/server/config/automations/mail.js
@@ -1,17 +1,15 @@
 'use strict';
 
 var _ = require('lodash');
-var config = require('../environment');
 var moment = require('moment');
-// var stringifyObject = require('stringify-object');
+var emitter = require('cluster-emitter');
 
-var sequelize = require('../../models').sequelize;
 var Automation = require('../../models').Automation;
 var MailRoom = require('../../models').MailRoom;
 var activeMailAutomations = {};
 
 function executeAutomation(id) {
-  console.log('Executing Mail Automation ', id);
+  console.log('[Automation] Executing Mail', id);
   var _mailAutomation;
   return Automation
     .scope('all')
@@ -55,7 +53,9 @@ function executeAutomation(id) {
       });
     })
     .catch(function(err) {
-      console.log('Mail Automation exec error', err);
+      console.error('[Automation] Error in Mail exec');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 }
 
@@ -68,7 +68,9 @@ function setStatus(ticketId, newStatus) {
       }
     })
     .catch(function(err) {
-      console.log('Automatic mail status error', err);
+      console.error('[Automation] Error in Mail setStatus');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 }
 
@@ -120,7 +122,7 @@ function getCondition(condition) {
 }
 
 function createInterval(mailAutomation) {
-  console.log('Mail Automation ', mailAutomation.id, ' set with timeout ', mailAutomation.timeout * 60 * 1000);
+  console.log('[Automation] Mail', mailAutomation.id, 'set with timeout', mailAutomation.timeout * 60 * 1000);
   activeMailAutomations['interval' + mailAutomation.id] = setInterval(function() {
     executeAutomation(mailAutomation.id);
   }, mailAutomation.timeout * 60 * 1000);
@@ -128,31 +130,39 @@ function createInterval(mailAutomation) {
 
 module.exports = function() {
 
-  Automation.afterCreate(function(doc, options) {
-    console.log('Mail Automation ', doc.id, ' created, the status is ', doc.status);
-    if (doc.status && doc.channel === 'mail') {
-      createInterval(doc);
+  console.log('[Automation] Mail service started');
+
+  emitter.on('Automation.afterCreate', function(doc, options) {
+    if (doc.channel === 'mail') {
+      console.log('[Automation] Mail', doc.id, 'created, the status is', doc.status);
+      if (doc.status) {
+        createInterval(doc);
+      }
     }
   });
 
-  Automation.afterUpdate(function(doc, options) {
-    console.log('Mail Automation ', doc.id, ' updated, the status is ', doc.status);
-    if (activeMailAutomations['interval' + doc.id]) {
-      console.log('Mail automation unset ', doc.id);
-      clearInterval(activeMailAutomations['interval' + doc.id]);
-      delete activeMailAutomations['interval' + doc.id];
-    }
-    if (doc.status && doc.channel === 'mail') {
-      createInterval(doc);
+  emitter.on('Automation.afterUpdate', function(doc, options) {
+    if (doc.channel === 'mail') {
+      console.log('[Automation] Mail', doc.id, 'updated, the status is', doc.status);
+      if (activeMailAutomations['interval' + doc.id]) {
+        console.log('[Automation] Mail unset ', doc.id);
+        clearInterval(activeMailAutomations['interval' + doc.id]);
+        delete activeMailAutomations['interval' + doc.id];
+      }
+      if (doc.status) {
+        createInterval(doc);
+      }
     }
   });
 
-  Automation.afterDelete(function(doc, options) {
-    console.log('Mail Automation ', doc.id, ' deleted');
-    if (activeMailAutomations['interval' + doc.id]) {
-      console.log('Mail automation unset ', doc.id);
-      clearInterval(activeMailAutomations['interval' + doc.id]);
-      delete activeMailAutomations['interval' + doc.id];
+  emitter.on('Automation.afterDelete', function(doc, options) {
+    if (doc.channel === 'mail') {
+      console.log('[Automation] Mail', doc.id, ' deleted');
+      if (activeMailAutomations['interval' + doc.id]) {
+        console.log('[Automation] Mail unset ', doc.id);
+        clearInterval(activeMailAutomations['interval' + doc.id]);
+        delete activeMailAutomations['interval' + doc.id];
+      }
     }
   });
 
@@ -167,11 +177,16 @@ module.exports = function() {
     })
     .then(function(mailAutomations) {
 
+      console.log('[Automation] Mail are', mailAutomations.length);
+
       mailAutomations.forEach(function(mailAutomation) {
         createInterval(mailAutomation);
       });
+
     })
     .catch(function(err) {
-      console.log('Mail Automation init error', err);
+      console.error('[Automation] Error in Mail init');
+      console.error('[Automation] Message:', err.message);
+      console.error('[Automation] Stack:', err.stack);
     });
 };
diff --git a/server/models/mail_server_out.js b/server/models/mail_server_out.js
index cb5da6e..55a844f 100644
--- a/server/models/mail_server_out.js
+++ b/server/models/mail_server_out.js
@@ -1,6 +1,8 @@
 /**
  *
  */
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
 
 	var MailServerOut = sequelize.define('MailServerOut', {
@@ -22,7 +24,18 @@ module.exports = function(sequelize, DataTypes) {
 		},
 		source: DataTypes.STRING
 	}, {
-		tableName: 'mail_servers_out'
+		tableName: 'mail_servers_out',
+		hooks: {
+			afterCreate: function(doc) {
+				emitter.to(['master']).emit('MailServerOut.afterCreate', doc);
+			},
+			afterUpdate: function(doc) {
+				emitter.to(['master']).emit('MailServerOut.afterUpdate', doc);
+			},
+			afterDestroy: function(doc) {
+				emitter.to(['master']).emit('MailServerOut.afterDestroy', doc);
+			}
+		}
 	});
 
 	return MailServerOut;
diff --git a/server/models/sms_account.js b/server/models/sms_account.js
index 7e38044..b53d4f0 100644
--- a/server/models/sms_account.js
+++ b/server/models/sms_account.js
@@ -1,5 +1,7 @@
 'use strict';
 
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
   var SmsAccount = sequelize.define('SmsAccount', {
     name: {
@@ -73,6 +75,17 @@ module.exports = function(sequelize, DataTypes) {
     }
   }, {
     tableName: 'sms_accounts',
+    hooks: {
+      afterCreate: function(doc) {
+        emitter.to(['master']).emit('SmsAccount.afterCreate', doc);
+      },
+      afterUpdate: function(doc) {
+        emitter.to(['master']).emit('SmsAccount.afterUpdate', doc);
+      },
+      afterDestroy: function(doc) {
+        emitter.to(['master']).emit('SmsAccount.afterDestroy', doc);
+      }
+    },
     associate: function(models) {
       SmsAccount.hasMany(models.SmsRoom);
       SmsAccount.hasMany(models.SmsApplication, {
diff --git a/server/models/square_odbc.js b/server/models/square_odbc.js
index a8a9bf8..c6bf132 100644
--- a/server/models/square_odbc.js
+++ b/server/models/square_odbc.js
@@ -1,5 +1,7 @@
 'use strict';
 
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
 
   var SquareOdbc = sequelize.define('SquareOdbc', {
@@ -16,7 +18,18 @@ module.exports = function(sequelize, DataTypes) {
     },
     description: DataTypes.STRING
   }, {
-    tableName: 'square_odbc'
+    tableName: 'square_odbc',
+    hooks: {
+      afterCreate: function(doc) {
+        emitter.to(['master']).emit('SquareOdbc.afterCreate', doc);
+      },
+      afterUpdate: function(doc) {
+        emitter.to(['master']).emit('SquareOdbc.afterUpdate', doc);
+      },
+      afterDestroy: function(doc) {
+        emitter.to(['master']).emit('SquareOdbc.afterDestroy', doc);
+      }
+    }
   });
 
   return SquareOdbc;
diff --git a/server/models/square_project.js b/server/models/square_project.js
index 7c28c70..61dfb71 100644
--- a/server/models/square_project.js
+++ b/server/models/square_project.js
@@ -1,5 +1,7 @@
 'use strict';
 
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
 
   var SquareProject = sequelize.define('SquareProject', {
@@ -23,6 +25,17 @@ module.exports = function(sequelize, DataTypes) {
     }
   }, {
     tableName: 'square_projects',
+    hooks: {
+      afterCreate: function(doc) {
+        emitter.to(['master']).emit('SquareProject.afterCreate', doc);
+      },
+      afterUpdate: function(doc) {
+        emitter.to(['master']).emit('SquareProject.afterUpdate', doc);
+      },
+      afterDestroy: function(doc) {
+        emitter.to(['master']).emit('SquareProject.afterDestroy', doc);
+      }
+    }
   });
 
   return SquareProject;
diff --git a/server/models/square_recording.js b/server/models/square_recording.js
index 611871a..929c747 100644
--- a/server/models/square_recording.js
+++ b/server/models/square_recording.js
@@ -2,6 +2,9 @@
  * Square recordings Model
  */
 
+var emitter = require('cluster-emitter');
+
+
 var crypto = require('crypto');
 
 module.exports = function(sequelize, DataTypes) {
@@ -20,7 +23,18 @@ module.exports = function(sequelize, DataTypes) {
 		filename: DataTypes.STRING,
 		savePath: DataTypes.STRING
 	}, {
-		tableName: 'square_recordings'
+		tableName: 'square_recordings',
+		hooks: {
+			afterCreate: function(doc) {
+				emitter.to(['master']).emit('SquareRecording.afterCreate', doc);
+			},
+			afterUpdate: function(doc) {
+				emitter.to(['master']).emit('SquareRecording.afterUpdate', doc);
+			},
+			afterDestroy: function(doc) {
+				emitter.to(['master']).emit('SquareRecording.afterDestroy', doc);
+			}
+		}
 	});
 
 	return SquareRecording;
diff --git a/server/models/template.js b/server/models/template.js
index 6ded5d0..6b8f1a1 100644
--- a/server/models/template.js
+++ b/server/models/template.js
@@ -3,6 +3,7 @@
  */
 
 var crypto = require('crypto');
+var emitter = require('cluster-emitter');
 
 module.exports = function(sequelize, DataTypes) {
 
@@ -12,7 +13,18 @@ module.exports = function(sequelize, DataTypes) {
 		subject: DataTypes.STRING,
 		html: DataTypes.TEXT
 	}, {
-		tableName: 'tools_templates'
+		tableName: 'tools_templates',
+		hooks: {
+			afterCreate: function(doc) {
+				emitter.to(['master']).emit('Template.afterCreate', doc);
+			},
+			afterUpdate: function(doc) {
+				emitter.to(['master']).emit('Template.afterUpdate', doc);
+			},
+			afterDestroy: function(doc) {
+				emitter.to(['master']).emit('Template.afterDestroy', doc);
+			}
+		}
 	});
 
 	return Template;
diff --git a/server/models/tools_automation.js b/server/models/tools_automation.js
index 67c4c74..22fe6a9 100644
--- a/server/models/tools_automation.js
+++ b/server/models/tools_automation.js
@@ -2,6 +2,8 @@
  * Automation Model
  */
 
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
 
   var Automation = sequelize.define('Automation', {
@@ -18,6 +20,17 @@ module.exports = function(sequelize, DataTypes) {
     }
   }, {
     tableName: 'tools_automations',
+    hooks: {
+      afterCreate: function(doc, options) {
+        emitter.to(['master']).emit('Automation.afterCreate', doc);
+      },
+      afterUpdate: function(doc, options) {
+        emitter.to(['master']).emit('Automation.afterUpdate', doc);
+      },
+      afterDelete: function(doc, options) {
+        emitter.to(['master']).emit('Automation.afterDelete', doc);
+      }
+    },
     associate: function(models) {
       Automation.hasMany(models.ToolsCondition, {
         as: {
diff --git a/server/models/tools_interval.js b/server/models/tools_interval.js
index de98180..b223bde 100644
--- a/server/models/tools_interval.js
+++ b/server/models/tools_interval.js
@@ -2,6 +2,8 @@
 
 const emitter = require('cluster-emitter');
 
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
   var Interval = sequelize.define('Interval', {
     name: {
@@ -14,6 +16,17 @@ module.exports = function(sequelize, DataTypes) {
     }
   }, {
     tableName: 'tools_intervals',
+    hooks: {
+      afterCreate: function(doc) {
+        emitter.to(['master']).emit('Interval.afterCreate', doc);
+      },
+      afterUpdate: function(doc) {
+        emitter.to(['master']).emit('Interval.afterUpdate', doc);
+      },
+      afterDestroy: function(doc) {
+        emitter.to(['master']).emit('Interval.afterDestroy', doc);
+      }
+    },
     associate: function(models) {
       Interval.hasMany(models.Interval, {
         as: 'SubIntervals',
diff --git a/server/models/tools_sound.js b/server/models/tools_sound.js
index 1e44ba9..8762e09 100644
--- a/server/models/tools_sound.js
+++ b/server/models/tools_sound.js
@@ -1,5 +1,8 @@
 'use strict';
 
+var emitter = require('cluster-emitter');
+
+
 module.exports = function(sequelize, DataTypes) {
 
 	var Sound = sequelize.define('Sound', {
@@ -29,7 +32,18 @@ module.exports = function(sequelize, DataTypes) {
 		converted_bitRate: DataTypes.BIGINT,
 		converted_sampleRate: DataTypes.INTEGER
 	}, {
-		tableName: 'tools_sounds'
+		tableName: 'tools_sounds',
+		hooks: {
+			afterCreate: function(doc) {
+				emitter.to(['master']).emit('Sound.afterCreate', doc);
+			},
+			afterUpdate: function(doc) {
+				emitter.to(['master']).emit('Sound.afterUpdate', doc);
+			},
+			afterDestroy: function(doc) {
+				emitter.to(['master']).emit('Sound.afterDestroy', doc);
+			}
+		}
 	});
 
 	return Sound;
diff --git a/server/models/tools_variable.js b/server/models/tools_variable.js
index a874a6d..8196d55 100644
--- a/server/models/tools_variable.js
+++ b/server/models/tools_variable.js
@@ -1,5 +1,7 @@
 'use strict';
 
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
 
   var Variable = sequelize.define('Variable', {
@@ -14,6 +16,17 @@ module.exports = function(sequelize, DataTypes) {
     description: DataTypes.STRING
   }, {
     tableName: 'tools_variables',
+    hooks: {
+      afterCreate: function(doc) {
+        emitter.to(['master']).emit('Variable.afterCreate', doc);
+      },
+      afterUpdate: function(doc) {
+        emitter.to(['master']).emit('Variable.afterUpdate', doc);
+      },
+      afterDestroy: function(doc) {
+        emitter.to(['master']).emit('Variable.afterDestroy', doc);
+      }
+    },
     associate: function(models) {
       Variable.hasMany(models.ZendeskField);
       Variable.hasMany(models.DeskField);
diff --git a/server/models/user.js b/server/models/user.js
index 6e99f69..440a54a 100644
--- a/server/models/user.js
+++ b/server/models/user.js
@@ -1,11 +1,11 @@
 'use strict';
 
-const crypto = require('crypto');
-const md5 = require('md5');
-const _ = require('lodash');
-const moment = require('moment');
-const emitter = require('cluster-emitter');
-const VoiceQueue = require('.').VoiceQueue;
+var crypto = require('crypto');
+var md5 = require('md5');
+var _ = require('lodash');
+var moment = require('moment');
+var VoiceQueue = require('.').VoiceQueue;
+var emitter = require('cluster-emitter');
 
 module.exports = function(sequelize, DataTypes) {
   var User = sequelize.define('User', {
@@ -744,6 +744,17 @@ module.exports = function(sequelize, DataTypes) {
     }
   }, {
     tableName: 'users',
+    hooks: {
+      afterCreate: function(doc) {
+        emitter.to(['master']).emit('User.afterCreate', doc);
+      },
+      afterUpdate: function(doc) {
+        emitter.to(['master']).emit('User.afterUpdate', doc);
+      },
+      afterDestroy: function(doc) {
+        emitter.to(['master']).emit('User.afterDestroy', doc);
+      }
+    },
     instanceMethods: {
       /**
        * Authenticate - check if the passwords are the same
diff --git a/server/models/voice_queue.js b/server/models/voice_queue.js
index b193f1c..4c88b44 100644
--- a/server/models/voice_queue.js
+++ b/server/models/voice_queue.js
@@ -1,5 +1,7 @@
 /* jshint indent: 2 */
 
+var emitter = require('cluster-emitter');
+
 module.exports = function(sequelize, DataTypes) {
   var VoiceQueue = sequelize.define('VoiceQueue', {
     name: {
@@ -286,6 +288,17 @@ module.exports = function(sequelize, DataTypes) {
     }
   }, {
     tableName: 'voice_queues',
+    hooks: {
+      afterCreate: function(doc) {
+        emitter.to(['master']).emit('VoiceQueue.afterCreate', doc);
+      },
+      afterUpdate: function(doc) {
+        emitter.to(['master']).emit('VoiceQueue.afterUpdate', doc);
+      },
+      afterDestroy: function(doc) {
+        emitter.to(['master']).emit('VoiceQueue.afterDestroy', doc);
+      }
+    },
     associate: function(models) {
       VoiceQueue.belongsToMany(models.User, {
         through: models.UserHasVoiceQueue,