@tiledesk/tiledesk-server 2.9.2 → 2.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,13 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
+ # 2.9.4
9
+ - Update tybot-connector to 0.2.86
10
+ - Added time-slots management
11
+
12
+ # 2.9.3
13
+ - Added log for AMQP error in closeOnErr
14
+
8
15
  # 2.9.2
9
16
  - Updated tybot-connector to 0.2.84
10
17
 
package/models/project.js CHANGED
@@ -34,6 +34,9 @@ var ProjectSchema = new Schema({
34
34
  operatingHours: {
35
35
  type: Object,
36
36
  },
37
+ timeSlots: {
38
+ type: Object,
39
+ },
37
40
  settings: {
38
41
  type: Object,
39
42
  default: function () {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-server",
3
3
  "description": "The Tiledesk server module",
4
- "version": "2.9.2",
4
+ "version": "2.9.4",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -48,7 +48,7 @@
48
48
  "@tiledesk/tiledesk-rasa-connector": "^1.0.10",
49
49
  "@tiledesk/tiledesk-telegram-connector": "^0.1.14",
50
50
  "@tiledesk/tiledesk-train-jobworker": "^0.0.11",
51
- "@tiledesk/tiledesk-tybot-connector": "^0.2.84",
51
+ "@tiledesk/tiledesk-tybot-connector": "^0.2.86",
52
52
  "@tiledesk/tiledesk-whatsapp-connector": "^0.1.72",
53
53
  "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.8",
54
54
  "@tiledesk/tiledesk-sms-connector": "^0.1.7",
package/routes/project.js CHANGED
@@ -307,6 +307,10 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
307
307
  if (req.body.operatingHours!=undefined) {
308
308
  update.operatingHours = req.body.operatingHours;
309
309
  }
310
+
311
+ if (req.body.timeSlots!=undefined) {
312
+ update.timeSlots = req.body.timeSlots;
313
+ }
310
314
 
311
315
  if (req.body.settings!=undefined) {
312
316
  update.settings = req.body.settings;
@@ -849,16 +853,32 @@ router.get('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
849
853
 
850
854
  // GET ALL PROJECTS BY CURRENT USER ID. usaed by unisalento to know if a project is open
851
855
  router.get('/:projectid/isopen', function (req, res) {
852
- operatingHoursService.projectIsOpenNow(req.params.projectid, function (isOpen, err) {
853
- winston.debug('project', req.params.projectid, 'isopen: ', isOpen);
854
856
 
855
- if (err) {
856
- winston.error('Error getting projectIsOpenNow', err);
857
- return res.status(500).send({ success: false, msg: err });
858
- }
859
- res.json({"isopen":isOpen});
860
- });
857
+ let project_id = req.params.projectid;
858
+ // Check if a timeSlot is passed
859
+ if (req.query.timeSlot) {
860
+ let slot_id = req.query.timeSlot;
861
+ operatingHoursService.slotIsOpenNow(project_id, slot_id, (isOpen, err) => {
862
+
863
+ if (err) {
864
+ winston.error("Error getting slotIsOpenNow ", err);
865
+ return res.status(500).send({ success: false, error: err });
866
+ }
867
+ return res.status(200).send({ isopen: isOpen})
868
+ })
869
+
870
+ } else {
861
871
 
872
+ operatingHoursService.projectIsOpenNow(project_id, function (isOpen, err) {
873
+ winston.debug('project', project_id, 'isopen: ', isOpen);
874
+
875
+ if (err) {
876
+ winston.error('Error getting projectIsOpenNow', err);
877
+ return res.status(500).send({ success: false, msg: err });
878
+ }
879
+ return res.status(200).send({ isopen: isOpen})
880
+ });
881
+ }
862
882
  });
863
883
 
864
884
  //togli questo route da qui e mettilo in altra route
@@ -175,7 +175,101 @@ class OperatingHoursService {
175
175
 
176
176
  } // ./end projectIsOpenNow
177
177
 
178
+ slotIsOpenNow(projectId, slot_id, callback) {
178
179
 
180
+ let q = Project.findOne({ _id: projectId, status: 100});
181
+ if (cacheEnabler.project) {
182
+ q.cache(cacheUtil.longTTL, "projects:id:"+projectId) //project_cache
183
+ winston.debug('project cache enabled for slotIsOpenNow');
184
+ }
185
+ q.exec( async (err, project) => {
186
+
187
+ if (err) {
188
+ winston.error("(slotIsOpenNow) Error getting project: ", err);
189
+ callback(null, { errorCode: 1000, msg: "Error getting project." })
190
+ return;
191
+ }
192
+ if (!project) {
193
+ winston.warn("(slotIsOpenNow) Project not found with id: " + projectId);
194
+ callback(null, { errorCode: 1010, msg: 'Project not found for id' + projectId });
195
+ return;
196
+ }
197
+
198
+ // Return ALWAYS true if the plan is free, trial is expired or the subscription is not active
199
+ if (project.profile && (project.profile.type === 'free' && project.trialExpired === true) || (project.profile.type === 'payment' && project.isActiveSubscription === false)) {
200
+ winston.debug('(slotIsOpenNow) Trial Expired or Subscription NOT Active')
201
+ callback(true, null) ;
202
+ return;
203
+ }
204
+
205
+ if (!project.timeSlots) {
206
+ winston.warn("(slotIsOpenNow) No time slots specified for the project " + projectId);
207
+ callback(true, null)
208
+ return
209
+ }
210
+
211
+ let timeSlot = project.timeSlots[slot_id];
212
+ console.log("timeSlot: ", timeSlot);
213
+
214
+ if (!timeSlot) {
215
+ callback(null, { errorCode: 1030, msg: 'Slot not found with id ' + slot_id })
216
+ return;
217
+ }
218
+
219
+ if (timeSlot.active == false) {
220
+ winston.verbose("(slotIsOpenNow) selected slot is not active")
221
+ callback(true, null);
222
+ return;
223
+ }
224
+
225
+ if (!timeSlot.hours) {
226
+ callback(null, { errorCode: 1020, msg: 'Operating hours is empty' });
227
+ return;
228
+ }
229
+
230
+ const hours = JSON.parse(timeSlot.hours);
231
+ const tzname = hours.tzname;
232
+ delete hours.tzname;
233
+
234
+ // Get the current time in the specified timezone
235
+ const currentTime = moment_tz.tz(tzname);
236
+ const currentWeekday = currentTime.isoWeekday();
237
+
238
+ const daySlots = hours[currentWeekday];
239
+ if (!daySlots) {
240
+ callback(false, null)
241
+ }
242
+
243
+ let promises = [];
244
+
245
+ daySlots.forEach((slot) => {
246
+ promises.push(slotCheck(currentTime, slot))
247
+ })
248
+
249
+ await Promise.all(promises).then((resp) => {
250
+ if (resp.indexOf(true) != -1) {
251
+ callback(true, null);
252
+ return;
253
+ }
254
+ callback(false, null);
255
+ return;
256
+ })
257
+ })
258
+ }
259
+ }
260
+
261
+ function slotCheck(currentTime, slot) {
262
+ return new Promise((resolve) => {
263
+
264
+ const startTime = moment_tz(slot.start, 'HH:mm');
265
+ const endTime = moment_tz(slot.end, 'HH:mm');
266
+
267
+ if (currentTime.isBetween(startTime, endTime, null, '[)')) {
268
+ resolve(true)
269
+ } else {
270
+ resolve(false);
271
+ }
272
+ })
179
273
  }
180
274
 
181
275
  function addOrSubstractProjcTzOffsetFromDateNow(prjcTimezoneName) {
@@ -2,7 +2,7 @@
2
2
  process.env.NODE_ENV = 'test';
3
3
  process.env.ADMIN_EMAIL = "admin@tiledesk.com";
4
4
 
5
- let log = false;
5
+ let log = true;
6
6
  var projectService = require('../services/projectService');
7
7
  var userService = require('../services/userService');
8
8
 
@@ -19,6 +19,26 @@ const path = require('path');
19
19
  var expect = chai.expect;
20
20
  var assert = chai.assert;
21
21
 
22
+ let timeSlotsSample = {
23
+ "819559cc": {
24
+ name: "Slot1",
25
+ active: true,
26
+ hours: "{\"1\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"3\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"5\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"tzname\":\"Europe/Rome\"}"
27
+ },
28
+ "5d4368de": {
29
+ name: "Slot2",
30
+ active: true,
31
+ hours: "{\"0\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"6\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"tzname\":\"Europe/Rome\"}"
32
+ },
33
+ "2975ec45": {
34
+ name: "Slot3",
35
+ active: false,
36
+ hours: "{\"0\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"6\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"tzname\":\"Europe/Rome\"}"
37
+ }
38
+ }
39
+
40
+
41
+
22
42
  chai.use(chaiHttp);
23
43
 
24
44
  describe('ProjectRoute', () => {
@@ -50,7 +70,7 @@ describe('ProjectRoute', () => {
50
70
  // .put('/projects/' + savedProject._id + "/update")
51
71
  .put('/projects/' + savedProject._id)
52
72
  .set('Authorization', superadmin_token)
53
- .send({ profile: { name: "Custom", quotes: { kbs: 1000} } })
73
+ .send({ profile: { name: "Custom", quotes: { kbs: 1000 } } })
54
74
  .end((err, res) => {
55
75
 
56
76
  if (log) { console.log("update project profile res.body: ", res.body) };
@@ -78,7 +98,7 @@ describe('ProjectRoute', () => {
78
98
  .put('/projects/' + savedProject._id)
79
99
  // .put('/projects/' + savedProject._id + "/update")
80
100
  .auth(email, pwd)
81
- .send({ profile: { name: "Custom", quotes: { kbs: 1000} } })
101
+ .send({ profile: { name: "Custom", quotes: { kbs: 1000 } } })
82
102
  .end((err, res) => {
83
103
 
84
104
  if (log) { console.log("update project profile res.body: ", res.body) };
@@ -90,6 +110,72 @@ describe('ProjectRoute', () => {
90
110
  })
91
111
  })
92
112
  }).timeout(10000)
113
+
114
+ it('updateProjectTimeSlots', (done) => {
115
+
116
+ var email = "test-signup-" + Date.now() + "@email.com";
117
+ var pwd = "pwd";
118
+
119
+ userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
120
+ projectService.create("test-project-create", savedUser._id).then((savedProject) => {
121
+
122
+ chai.request(server)
123
+ // .put('/projects/' + savedProject._id + "/update")
124
+ .put('/projects/' + savedProject._id)
125
+ .auth(email, pwd)
126
+ .send({ timeSlots: timeSlotsSample })
127
+ .end((err, res) => {
128
+
129
+ if (log) { console.log("update project time slots res.body: ", res.body) };
130
+ res.should.have.status(200);
131
+ res.body.should.be.a('object');
132
+
133
+ done();
134
+ })
135
+ })
136
+ })
137
+ }).timeout(10000)
138
+
139
+ it('isOpenTimeSlot', (done) => {
140
+
141
+ var email = "test-signup-" + Date.now() + "@email.com";
142
+ var pwd = "pwd";
143
+
144
+ userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
145
+ projectService.create("test-project-create", savedUser._id).then((savedProject) => {
146
+
147
+ chai.request(server)
148
+ // .put('/projects/' + savedProject._id + "/update")
149
+ .put('/projects/' + savedProject._id)
150
+ .auth(email, pwd)
151
+ .send({ timeSlots: timeSlotsSample })
152
+ .end((err, res) => {
153
+
154
+ if (log) { console.log("update project time slots res.body: ", res.body) };
155
+ res.should.have.status(200);
156
+ res.body.should.be.a('object');
157
+
158
+ chai.request(server)
159
+ .get('/projects/' + savedProject._id + '/isopen?timeSlot=819559cc')
160
+ .auth(email, pwd)
161
+ .end((err, res) => {
162
+
163
+ if (err) { console.error("err: ", err) };
164
+ if (log) { console.log("res.body isopen: ", res.body) };
165
+
166
+ // Unable to do other checks due to currentTime change.
167
+ res.should.have.status(200);
168
+
169
+ done();
170
+
171
+ })
172
+ })
173
+
174
+
175
+ })
176
+ })
177
+ }).timeout(10000)
178
+
93
179
  });
94
180
 
95
181
  });
@@ -322,7 +322,7 @@ processMsg2(msg) {
322
322
 
323
323
  closeOnErr(err) {
324
324
  if (!err) return false;
325
- if (this.debug) {console.log("[JobWorker] AMQP error", err);}
325
+ console.error("[JobWorker] AMQP error", err);
326
326
  this.amqpConn.close();
327
327
  return true;
328
328
  }