@tiledesk/tiledesk-server 2.9.26 → 2.9.28
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +9 -0
- package/package.json +2 -2
- package/pubmodules/pubModulesManager.js +41 -41
- package/pubmodules/routing-queue/listenerQueued.js +72 -27
- package/routes/faq_kb.js +1 -1
- package/routes/kb.js +2 -1
- package/routes/message.js +55 -50
- package/routes/request.js +581 -47
- package/routes/users.js +4 -7
- package/services/QuoteManager.js +104 -16
- package/services/emailService.js +11 -2
- package/services/operatingHoursService.js +1 -0
- package/services/projectService.js +21 -0
- package/services/requestService.js +344 -9
- package/template/email/redirectToDesktopEmail.html +2 -2
- package/test/mock/projectMock.js +29 -1
- package/test/projectRoute.js +86 -3
- package/test/quoteManager.js +77 -5
- package/test/requestRoute.js +42 -0
- package/websocket/webSocketServer.js +1 -1
@@ -17,8 +17,10 @@ var UIDGenerator = require("../utils/UIDGenerator");
|
|
17
17
|
const { TdCache } = require('../utils/TdCache');
|
18
18
|
const { QuoteManager } = require('./QuoteManager');
|
19
19
|
var configGlobal = require('../config/global');
|
20
|
+
const projectService = require('./projectService');
|
20
21
|
const axios = require("axios").default;
|
21
22
|
|
23
|
+
|
22
24
|
const apiUrl = process.env.API_URL || configGlobal.apiUrl;
|
23
25
|
|
24
26
|
let tdCache = new TdCache({
|
@@ -272,7 +274,7 @@ class RequestService {
|
|
272
274
|
var beforeParticipants = requestBeforeRoute.participants;
|
273
275
|
winston.debug("beforeParticipants: ", beforeParticipants);
|
274
276
|
|
275
|
-
return that.routeInternal(request, departmentid, id_project, nobot).then(function (routedRequest) {
|
277
|
+
return that.routeInternal(request, departmentid, id_project, nobot).then( async function (routedRequest) {
|
276
278
|
|
277
279
|
winston.debug("after routeInternal", routedRequest);
|
278
280
|
// winston.info("requestBeforeRoute.participants " +requestBeforeRoute.request_id , requestBeforeRoute.participants);
|
@@ -286,13 +288,22 @@ class RequestService {
|
|
286
288
|
winston.debug("beforeDepartmentId:" + beforeDepartmentId);
|
287
289
|
}
|
288
290
|
|
291
|
+
|
289
292
|
let afterDepartmentId;
|
290
293
|
if (routedRequest.department) {
|
291
294
|
afterDepartmentId = routedRequest.department.toString();
|
292
295
|
winston.debug("afterDepartmentId:" + afterDepartmentId);
|
293
296
|
}
|
294
297
|
|
295
|
-
|
298
|
+
winston.debug("requestBefore status: ", requestBeforeRoute.status)
|
299
|
+
winston.debug("routedRequest status: ", routedRequest.status)
|
300
|
+
/**
|
301
|
+
* Case 1
|
302
|
+
* After internal routing:
|
303
|
+
* - same STATUS
|
304
|
+
* - same DEPARTMENT
|
305
|
+
* - same PARTICIPANTS
|
306
|
+
*/
|
296
307
|
if (requestBeforeRoute.status === routedRequest.status &&
|
297
308
|
beforeDepartmentId === afterDepartmentId &&
|
298
309
|
requestUtil.arraysEqual(beforeParticipants, routedRequest.participants)) {
|
@@ -317,6 +328,62 @@ class RequestService {
|
|
317
328
|
});
|
318
329
|
}
|
319
330
|
|
331
|
+
let project = await projectService.getCachedProject(id_project).catch((err) => {
|
332
|
+
winston.warn("Error getting cached project. Skip conversation quota check.")
|
333
|
+
winston.warn("Getting cached project error: ", err)
|
334
|
+
})
|
335
|
+
|
336
|
+
|
337
|
+
let isTestConversation = false;
|
338
|
+
let isVoiceConversation = false;
|
339
|
+
let isStandardConversation = false;
|
340
|
+
|
341
|
+
let payload = {
|
342
|
+
project: project,
|
343
|
+
request: request
|
344
|
+
}
|
345
|
+
|
346
|
+
if (request.attributes && request.attributes.sourcePage && (request.attributes.sourcePage.indexOf("td_draft=true") > -1)) {
|
347
|
+
winston.verbose("is a test conversation --> skip quote availability check")
|
348
|
+
isTestConversation = true;
|
349
|
+
}
|
350
|
+
else if (request.channel && (request.channel.name === 'voice-vxml')) {
|
351
|
+
winston.verbose("is a voice conversation --> skip quote availability check")
|
352
|
+
isVoiceConversation = true;
|
353
|
+
}
|
354
|
+
else {
|
355
|
+
isStandardConversation = true;
|
356
|
+
let available = await qm.checkQuote(project, request, 'requests');
|
357
|
+
if (available === false) {
|
358
|
+
winston.info("Requests limits reached for project " + project._id)
|
359
|
+
return reject("Requests limits reached for project " + project._id);
|
360
|
+
}
|
361
|
+
}
|
362
|
+
|
363
|
+
/**
|
364
|
+
* Case 2 - Leaving TEMP status
|
365
|
+
* After internal routing:
|
366
|
+
* - STATUS changed from 50 to 100 or 200
|
367
|
+
*/
|
368
|
+
if (requestBeforeRoute.status === RequestConstants.TEMP && (routedRequest.status === RequestConstants.ASSIGNED || routedRequest.status === RequestConstants.UNASSIGNED)) {
|
369
|
+
// console.log("Case 2 - Leaving TEMP status")
|
370
|
+
if (isStandardConversation) {
|
371
|
+
requestEvent.emit('request.create.quote', payload);
|
372
|
+
}
|
373
|
+
}
|
374
|
+
|
375
|
+
/**
|
376
|
+
* Case 3 - Conversation opened through proactive message
|
377
|
+
* After internal routing:
|
378
|
+
* - STATUS changed from undefined to 100
|
379
|
+
*/
|
380
|
+
if ((!requestBeforeRoute.status || requestBeforeRoute.status === undefined) && routedRequest.status === RequestConstants.ASSIGNED) {
|
381
|
+
// console.log("Case 3 - 'Proactive' request")
|
382
|
+
if (isStandardConversation) {
|
383
|
+
requestEvent.emit('request.create.quote', payload);
|
384
|
+
}
|
385
|
+
}
|
386
|
+
|
320
387
|
//cacheinvalidation
|
321
388
|
return routedRequest.save(function (err, savedRequest) {
|
322
389
|
// https://stackoverflow.com/questions/54792749/mongoose-versionerror-no-matching-document-found-for-id-when-document-is-being
|
@@ -469,6 +536,232 @@ class RequestService {
|
|
469
536
|
|
470
537
|
async create(request) {
|
471
538
|
|
539
|
+
if (!request.createdAt) {
|
540
|
+
request.createdAt = new Date();
|
541
|
+
}
|
542
|
+
|
543
|
+
var request_id = request.request_id;
|
544
|
+
var project_user_id = request.project_user_id;
|
545
|
+
var lead_id = request.lead_id;
|
546
|
+
var id_project = request.id_project;
|
547
|
+
var first_text = request.first_text;
|
548
|
+
var departmentid = request.departmentid;
|
549
|
+
var sourcePage = request.sourcePage;
|
550
|
+
var language = request.language;
|
551
|
+
var userAgent = request.userAgent;
|
552
|
+
var status = request.status;
|
553
|
+
var createdBy = request.createdBy;
|
554
|
+
var attributes = request.attributes;
|
555
|
+
var subject = request.subject;
|
556
|
+
var preflight = request.preflight;
|
557
|
+
var channel = request.channel;
|
558
|
+
var location = request.location;
|
559
|
+
var participants = request.participants || [];
|
560
|
+
var tags = request.tags;
|
561
|
+
var notes = request.notes;
|
562
|
+
var priority = request.priority;
|
563
|
+
var auto_close = request.auto_close;
|
564
|
+
var followers = request.followers;
|
565
|
+
let createdAt = request.createdAt;
|
566
|
+
|
567
|
+
if (!departmentid) {
|
568
|
+
departmentid = 'default';
|
569
|
+
}
|
570
|
+
|
571
|
+
if (!createdBy) {
|
572
|
+
if (project_user_id) {
|
573
|
+
createdBy = project_user_id;
|
574
|
+
} else {
|
575
|
+
createdBy = "system";
|
576
|
+
}
|
577
|
+
}
|
578
|
+
|
579
|
+
// Utils
|
580
|
+
let payload;
|
581
|
+
let isTestConversation = false;
|
582
|
+
let isVoiceConversation = false;
|
583
|
+
let isStandardConversation = false;
|
584
|
+
var that = this;
|
585
|
+
|
586
|
+
return new Promise( async (resolve, reject) => {
|
587
|
+
var context = {
|
588
|
+
request: {
|
589
|
+
request_id: request_id, project_user_id: project_user_id, lead_id: lead_id, id_project: id_project,
|
590
|
+
first_text: first_text, departmentid: departmentid, sourcePage: sourcePage, language: language, userAgent: userAgent, status: status,
|
591
|
+
createdBy: createdBy, attributes: attributes, subject: subject, preflight: preflight, channel: channel, location: location,
|
592
|
+
participants: participants, tags: tags, notes: notes,
|
593
|
+
priority: priority, auto_close: auto_close, followers: followers
|
594
|
+
}
|
595
|
+
};
|
596
|
+
winston.debug("context", context);
|
597
|
+
|
598
|
+
var participantsAgents = [];
|
599
|
+
var participantsBots = [];
|
600
|
+
var hasBot = false;
|
601
|
+
var dep_id = undefined;
|
602
|
+
var assigned_at = undefined;
|
603
|
+
var agents = [];
|
604
|
+
var snapshot = {};
|
605
|
+
|
606
|
+
try {
|
607
|
+
// (method) DepartmentService.getOperators(departmentid: any, projectid: any, nobot: any, disableWebHookCall: any, context: any): Promise<any>
|
608
|
+
var result = await departmentService.getOperators(departmentid, id_project, false, undefined, context);
|
609
|
+
winston.debug("getOperators", result);
|
610
|
+
|
611
|
+
} catch (err) {
|
612
|
+
return reject(err);
|
613
|
+
}
|
614
|
+
|
615
|
+
agents = result.agents;
|
616
|
+
|
617
|
+
if (status == 50) {
|
618
|
+
// skip assignment
|
619
|
+
if (participants.length == 0) {
|
620
|
+
dep_id = result.department._id;
|
621
|
+
}
|
622
|
+
} else {
|
623
|
+
|
624
|
+
let project = await projectService.getCachedProject(id_project).catch((err) => {
|
625
|
+
winston.warn("Error getting cached project. Skip conversation quota check.")
|
626
|
+
winston.warn("Getting cached project error: ", err)
|
627
|
+
})
|
628
|
+
|
629
|
+
payload = {
|
630
|
+
project: project,
|
631
|
+
request: request
|
632
|
+
}
|
633
|
+
|
634
|
+
if (attributes && attributes.sourcePage && (attributes.sourcePage.indexOf("td_draft=true") > -1)) {
|
635
|
+
winston.verbose("is a test conversation --> skip quote availability check")
|
636
|
+
isTestConversation = true;
|
637
|
+
}
|
638
|
+
else if (channel && (channel.name === 'voice-vxml')) {
|
639
|
+
winston.verbose("is a voice conversation --> skip quote availability check")
|
640
|
+
isVoiceConversation = true;
|
641
|
+
}
|
642
|
+
else {
|
643
|
+
isStandardConversation = true;
|
644
|
+
let available = await qm.checkQuote(project, request, 'requests');
|
645
|
+
if (available === false) {
|
646
|
+
winston.info("Requests limits reached for project " + project._id)
|
647
|
+
return reject("Requests limits reached for project " + project._id);
|
648
|
+
}
|
649
|
+
}
|
650
|
+
|
651
|
+
|
652
|
+
if (participants.length == 0) {
|
653
|
+
if (result.operators && result.operators.length > 0) {
|
654
|
+
participants.push(result.operators[0].id_user.toString());
|
655
|
+
}
|
656
|
+
// for preflight it is important to save agents in req for trigger. try to optimize it
|
657
|
+
dep_id = result.department._id;
|
658
|
+
}
|
659
|
+
|
660
|
+
if (participants.length > 0) {
|
661
|
+
status = RequestConstants.ASSIGNED;
|
662
|
+
// botprefix
|
663
|
+
if (participants[0].startsWith("bot_")) {
|
664
|
+
|
665
|
+
hasBot = true;
|
666
|
+
winston.debug("hasBot:" + hasBot);
|
667
|
+
|
668
|
+
// botprefix
|
669
|
+
var assigned_operator_idStringBot = participants[0].replace("bot_", "");
|
670
|
+
winston.debug("assigned_operator_idStringBot:" + assigned_operator_idStringBot);
|
671
|
+
|
672
|
+
participantsBots.push(assigned_operator_idStringBot);
|
673
|
+
|
674
|
+
} else {
|
675
|
+
|
676
|
+
participantsAgents.push(participants[0]);
|
677
|
+
|
678
|
+
}
|
679
|
+
|
680
|
+
assigned_at = Date.now();
|
681
|
+
|
682
|
+
} else {
|
683
|
+
status = RequestConstants.UNASSIGNED;
|
684
|
+
}
|
685
|
+
}
|
686
|
+
|
687
|
+
if (dep_id) {
|
688
|
+
snapshot.department = result.department;
|
689
|
+
}
|
690
|
+
|
691
|
+
snapshot.agents = agents;
|
692
|
+
snapshot.availableAgentsCount = that.getAvailableAgentsCount(agents);
|
693
|
+
|
694
|
+
if (request.requester) {
|
695
|
+
snapshot.requester = request.requester;
|
696
|
+
}
|
697
|
+
if (request.lead) {
|
698
|
+
snapshot.lead = request.lead;
|
699
|
+
}
|
700
|
+
|
701
|
+
var newRequest = new Request({
|
702
|
+
request_id: request_id,
|
703
|
+
requester: project_user_id,
|
704
|
+
lead: lead_id,
|
705
|
+
first_text: first_text,
|
706
|
+
subject: subject,
|
707
|
+
status: status,
|
708
|
+
participants: participants,
|
709
|
+
participantsAgents: participantsAgents,
|
710
|
+
participantsBots: participantsBots,
|
711
|
+
hasBot: hasBot,
|
712
|
+
department: dep_id,
|
713
|
+
// agents: agents,
|
714
|
+
//others
|
715
|
+
sourcePage: sourcePage,
|
716
|
+
language: language,
|
717
|
+
userAgent: userAgent,
|
718
|
+
assigned_at: assigned_at,
|
719
|
+
attributes: attributes,
|
720
|
+
//standard
|
721
|
+
id_project: id_project,
|
722
|
+
createdBy: createdBy,
|
723
|
+
updatedBy: createdBy,
|
724
|
+
preflight: preflight,
|
725
|
+
channel: channel,
|
726
|
+
location: location,
|
727
|
+
snapshot: snapshot,
|
728
|
+
tags: tags,
|
729
|
+
notes: notes,
|
730
|
+
priority: priority,
|
731
|
+
auto_close: auto_close,
|
732
|
+
followers: followers,
|
733
|
+
createdAt: createdAt
|
734
|
+
});
|
735
|
+
|
736
|
+
if (isTestConversation) {
|
737
|
+
newRequest.draft = true;
|
738
|
+
}
|
739
|
+
|
740
|
+
winston.debug('newRequest.', newRequest);
|
741
|
+
|
742
|
+
//cacheinvalidation
|
743
|
+
return newRequest.save( async function (err, savedRequest) {
|
744
|
+
|
745
|
+
if (err) {
|
746
|
+
winston.error('RequestService error for method createWithIdAndRequester for newRequest' + JSON.stringify(newRequest), err);
|
747
|
+
return reject(err);
|
748
|
+
}
|
749
|
+
winston.debug("Request created", savedRequest.toObject());
|
750
|
+
|
751
|
+
requestEvent.emit('request.create.simple', savedRequest);
|
752
|
+
|
753
|
+
if (isStandardConversation) {
|
754
|
+
requestEvent.emit('request.create.quote', payload);;
|
755
|
+
}
|
756
|
+
|
757
|
+
return resolve(savedRequest);
|
758
|
+
|
759
|
+
});
|
760
|
+
})
|
761
|
+
}
|
762
|
+
|
763
|
+
async _create(request) {
|
764
|
+
|
472
765
|
var startDate = new Date();
|
473
766
|
|
474
767
|
if (!request.createdAt) {
|
@@ -512,6 +805,7 @@ class RequestService {
|
|
512
805
|
var followers = request.followers;
|
513
806
|
let createdAt = request.createdAt;
|
514
807
|
|
808
|
+
|
515
809
|
if (!departmentid) {
|
516
810
|
departmentid = 'default';
|
517
811
|
}
|
@@ -560,11 +854,12 @@ class RequestService {
|
|
560
854
|
isVoiceConversation = true;
|
561
855
|
}
|
562
856
|
else {
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
857
|
+
// console.log("! check quota moved")
|
858
|
+
// let available = await qm.checkQuote(p, request, 'requests');
|
859
|
+
// if (available === false) {
|
860
|
+
// winston.info("Requests limits reached for project " + p._id)
|
861
|
+
// return false;
|
862
|
+
// }
|
568
863
|
}
|
569
864
|
|
570
865
|
|
@@ -626,6 +921,18 @@ class RequestService {
|
|
626
921
|
|
627
922
|
status = RequestConstants.ASSIGNED;
|
628
923
|
|
924
|
+
/**
|
925
|
+
* QUOTAS - START!!!
|
926
|
+
*/
|
927
|
+
if (!isTestConversation && !isVoiceConversation) {
|
928
|
+
requestEvent.emit('request.create.quote', payload);
|
929
|
+
}
|
930
|
+
/**
|
931
|
+
* QUOTAS - END!!!
|
932
|
+
*/
|
933
|
+
|
934
|
+
|
935
|
+
|
629
936
|
// botprefix
|
630
937
|
if (participants[0].startsWith("bot_")) {
|
631
938
|
|
@@ -736,7 +1043,7 @@ class RequestService {
|
|
736
1043
|
requestEvent.emit('request.create.simple', savedRequest);
|
737
1044
|
|
738
1045
|
if (!isTestConversation && !isVoiceConversation) {
|
739
|
-
requestEvent.emit('request.create.quote', payload);;
|
1046
|
+
// requestEvent.emit('request.create.quote', payload);;
|
740
1047
|
}
|
741
1048
|
|
742
1049
|
return resolve(savedRequest);
|
@@ -752,7 +1059,7 @@ class RequestService {
|
|
752
1059
|
}
|
753
1060
|
|
754
1061
|
|
755
|
-
async
|
1062
|
+
async __create(request) {
|
756
1063
|
|
757
1064
|
var startDate = new Date();
|
758
1065
|
|
@@ -2505,6 +2812,34 @@ class RequestService {
|
|
2505
2812
|
|
2506
2813
|
}
|
2507
2814
|
|
2815
|
+
async getConversationsCount(id_project, status, preflight, hasBot, startDate, endDate) {
|
2816
|
+
return new Promise( async (resolve, reject) => {
|
2817
|
+
let query = { id_project: id_project, status: status, preflight: preflight};
|
2818
|
+
if (hasBot != null) {
|
2819
|
+
query.hasBot = hasBot;
|
2820
|
+
}
|
2821
|
+
if (status === 201) {
|
2822
|
+
query.status = {
|
2823
|
+
$in: [100,200]
|
2824
|
+
}
|
2825
|
+
}
|
2826
|
+
if (preflight === null) {
|
2827
|
+
delete query.preflight;
|
2828
|
+
}
|
2829
|
+
if (startDate && endDate) {
|
2830
|
+
query.createdAt = { $gte: startDate.toDate(), $lte: endDate.toDate() }
|
2831
|
+
}
|
2832
|
+
winston.debug("getConversationsCount query: ", query)
|
2833
|
+
let count = await Request.countDocuments(query).catch((err) => {
|
2834
|
+
winston.error("Error getting requests count: ", err);
|
2835
|
+
reject(err);
|
2836
|
+
})
|
2837
|
+
winston.verbose("Requests found for query " + JSON.stringify(query) + ": " + count);
|
2838
|
+
resolve(count)
|
2839
|
+
})
|
2840
|
+
}
|
2841
|
+
|
2842
|
+
|
2508
2843
|
}
|
2509
2844
|
|
2510
2845
|
|
@@ -167,7 +167,7 @@
|
|
167
167
|
style=" background-color: #ff8574 !important; border: none; color: white; padding: 6px 18px; text-align: center; text-decoration: none; display: inline-block; font-size: 14px; font-weight: 600; letter-spacing: 1px; margin: 4px 2px; cursor: pointer; border-radius: 8px;">
|
168
168
|
Enjoy Tiledesk
|
169
169
|
</a> -->
|
170
|
-
<a href="
|
170
|
+
<a href="{{redirect_url}}"
|
171
171
|
style=" background-color: #ff8574 !important; border: none; color: white; padding: 6px 18px; text-align: center; text-decoration: none; display: inline-block; font-size: 14px; font-weight: 600; letter-spacing: 1px; margin: 4px 2px; cursor: pointer; border-radius: 8px;">
|
172
172
|
Enjoy Tiledesk
|
173
173
|
</a>
|
@@ -184,7 +184,7 @@
|
|
184
184
|
{{baseScope.baseUrl}}/#/project/{{project_id}}/home
|
185
185
|
</a> -->
|
186
186
|
<a
|
187
|
-
href="
|
187
|
+
href="{{redirect_url}}">
|
188
188
|
{{baseScope.baseUrl}}/#/project/{{project_id}}/home
|
189
189
|
</a>
|
190
190
|
</div>
|
package/test/mock/projectMock.js
CHANGED
@@ -68,6 +68,7 @@ const mockProjectBasicPlan = {
|
|
68
68
|
"name": "mock-project",
|
69
69
|
"activeOperatingHours": false,
|
70
70
|
"createdBy": "64e36f5cbf72263f7c05ba36",
|
71
|
+
"isActiveSubscription": true,
|
71
72
|
"profile": {
|
72
73
|
"name": "Basic",
|
73
74
|
"trialDays": 14,
|
@@ -110,6 +111,33 @@ const mockProjectPremiumPlan = {
|
|
110
111
|
"createdAt": new Date('2023-10-16T08:45:54.058Z')
|
111
112
|
}
|
112
113
|
|
114
|
+
const mockProjectPremiumPlan2 = {
|
115
|
+
"_id": "64e36f5dbf72263f7c059999",
|
116
|
+
"status": 100,
|
117
|
+
"ipFilterEnabled": false,
|
118
|
+
"ipFilter": [],
|
119
|
+
"ipFilterDenyEnabled": false,
|
120
|
+
"ipFilterDeny": [],
|
121
|
+
"name": "mock-project",
|
122
|
+
"activeOperatingHours": false,
|
123
|
+
"createdBy": "64e36f5cbf72263f7c05ba36",
|
124
|
+
"isActiveSubscription": true,
|
125
|
+
"profile": {
|
126
|
+
"name": "Premium",
|
127
|
+
"trialDays": 14,
|
128
|
+
"agents": 0,
|
129
|
+
"type": "payment",
|
130
|
+
"subStart": new Date('2024-01-31T10:00:00.058Z')
|
131
|
+
},
|
132
|
+
"versions": 20115,
|
133
|
+
"channels": [
|
134
|
+
{
|
135
|
+
"name": "chat21"
|
136
|
+
}
|
137
|
+
],
|
138
|
+
"createdAt": new Date('2024-01-20T10:00:00.058Z')
|
139
|
+
}
|
140
|
+
|
113
141
|
const mockProjectCustomPlan = {
|
114
142
|
"_id": "64e36f5dbf72263f7c059999",
|
115
143
|
"status": 100,
|
@@ -167,4 +195,4 @@ const mockOldProjecPlusPlan = {
|
|
167
195
|
"ipFilterDenyEnabled": false
|
168
196
|
}
|
169
197
|
|
170
|
-
module.exports = { mockProjectUser, mockProjectFreeTrialPlan, mockProjectSandboxPlan, mockProjectBasicPlan, mockProjectPremiumPlan, mockProjectCustomPlan, mockOldProjecPlusPlan };
|
198
|
+
module.exports = { mockProjectUser, mockProjectFreeTrialPlan, mockProjectSandboxPlan, mockProjectBasicPlan, mockProjectPremiumPlan, mockProjectPremiumPlan2, mockProjectCustomPlan, mockOldProjecPlusPlan };
|
package/test/projectRoute.js
CHANGED
@@ -22,12 +22,13 @@ var Group = require('../models/group');
|
|
22
22
|
var expect = chai.expect;
|
23
23
|
var assert = chai.assert;
|
24
24
|
|
25
|
-
|
25
|
+
let operatingHours = '{"1":[{"start":"09:00","end":"13:00"},{"start":"14:00","end":"18:00"}],"2":[{"start":"09:00","end":"13:00"},{"start":"14:00","end":"18:00"}],"3":[{"start":"09:00","end":"11:00"},{"start":"14:00","end":"18:00"}],"4":[{"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"}';
|
26
26
|
let timeSlotsSample = {
|
27
27
|
"819559cc": {
|
28
28
|
name: "Slot1",
|
29
29
|
active: true,
|
30
|
-
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\":\"
|
30
|
+
//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\":\"America/Los_Angeles\"}"
|
31
|
+
hours: "{\"1\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"3\":[{\"start\":\"09:00\",\"end\":\"15:00\"},{\"start\":\"17:00\",\"end\":\"18:00\"}],\"5\":[{\"start\":\"09:00\",\"end\":\"13:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}],\"tzname\":\"Europe/Rome\"}"
|
31
32
|
},
|
32
33
|
"5d4368de": {
|
33
34
|
name: "Slot2",
|
@@ -115,6 +116,9 @@ describe('ProjectRoute', () => {
|
|
115
116
|
})
|
116
117
|
}).timeout(10000)
|
117
118
|
|
119
|
+
|
120
|
+
|
121
|
+
|
118
122
|
it('updateProjectTimeSlots', (done) => {
|
119
123
|
|
120
124
|
var email = "test-signup-" + Date.now() + "@email.com";
|
@@ -180,8 +184,47 @@ describe('ProjectRoute', () => {
|
|
180
184
|
})
|
181
185
|
}).timeout(10000)
|
182
186
|
|
183
|
-
it('
|
187
|
+
it('isOpenOperatingHours', (done) => {
|
188
|
+
|
189
|
+
var email = "test-signup-" + Date.now() + "@email.com";
|
190
|
+
var pwd = "pwd";
|
191
|
+
|
192
|
+
userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
|
193
|
+
projectService.create("test-project-create", savedUser._id).then((savedProject) => {
|
194
|
+
|
195
|
+
chai.request(server)
|
196
|
+
// .put('/projects/' + savedProject._id + "/update")
|
197
|
+
.put('/projects/' + savedProject._id)
|
198
|
+
.auth(email, pwd)
|
199
|
+
.send({ activeOperatingHours: true, operatingHours: operatingHours })
|
200
|
+
.end((err, res) => {
|
201
|
+
|
202
|
+
if (log) { console.log("update project time slots res.body: ", res.body) };
|
203
|
+
res.should.have.status(200);
|
204
|
+
res.body.should.be.a('object');
|
205
|
+
|
206
|
+
chai.request(server)
|
207
|
+
.get('/projects/' + savedProject._id + '/isopen')
|
208
|
+
.auth(email, pwd)
|
209
|
+
.end((err, res) => {
|
210
|
+
|
211
|
+
if (err) { console.error("err: ", err) };
|
212
|
+
if (log) { console.log("res.body isopen: ", res.body) };
|
213
|
+
|
214
|
+
// Unable to do other checks due to currentTime change.
|
215
|
+
res.should.have.status(200);
|
216
|
+
|
217
|
+
done();
|
218
|
+
|
219
|
+
})
|
220
|
+
})
|
221
|
+
|
222
|
+
|
223
|
+
})
|
224
|
+
})
|
225
|
+
}).timeout(10000)
|
184
226
|
|
227
|
+
it('availableUsers', (done) => {
|
185
228
|
var email = "test-signup-" + Date.now() + "@email.com";
|
186
229
|
var pwd = "pwd";
|
187
230
|
|
@@ -198,6 +241,46 @@ describe('ProjectRoute', () => {
|
|
198
241
|
|
199
242
|
done();
|
200
243
|
})
|
244
|
+
})
|
245
|
+
})
|
246
|
+
})
|
247
|
+
|
248
|
+
it('utcChecker', (done) => {
|
249
|
+
|
250
|
+
var email = "test-signup-" + Date.now() + "@email.com";
|
251
|
+
var pwd = "pwd";
|
252
|
+
|
253
|
+
userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
|
254
|
+
projectService.create("test-project-create", savedUser._id).then((savedProject) => {
|
255
|
+
|
256
|
+
chai.request(server)
|
257
|
+
// .put('/projects/' + savedProject._id + "/update")
|
258
|
+
.put('/projects/' + savedProject._id)
|
259
|
+
.auth(email, pwd)
|
260
|
+
.send({ timeSlots: timeSlotsSample })
|
261
|
+
.end((err, res) => {
|
262
|
+
|
263
|
+
if (log) { console.log("update project time slots res.body: ", res.body) };
|
264
|
+
res.should.have.status(200);
|
265
|
+
res.body.should.be.a('object');
|
266
|
+
|
267
|
+
chai.request(server)
|
268
|
+
.get('/projects/' + savedProject._id + '/isopen?timeSlot=819559cc')
|
269
|
+
.auth(email, pwd)
|
270
|
+
.end((err, res) => {
|
271
|
+
|
272
|
+
if (err) { console.error("err: ", err) };
|
273
|
+
if (log) { console.log("res.body isopen: ", res.body) };
|
274
|
+
|
275
|
+
// Unable to do other checks due to currentTime change.
|
276
|
+
res.should.have.status(200);
|
277
|
+
|
278
|
+
done();
|
279
|
+
|
280
|
+
})
|
281
|
+
})
|
282
|
+
|
283
|
+
|
201
284
|
})
|
202
285
|
})
|
203
286
|
}).timeout(10000)
|