@tiledesk/tiledesk-server 2.9.26 → 2.9.28
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 +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)
|