@tiledesk/tiledesk-server 2.7.26 → 2.8.0
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 +6 -0
- package/app.js +1 -1
- package/config/labels/widget.json +31 -0
- package/deploy.sh +1 -1
- package/event/emailEvent.js +58 -2
- package/models/faq.js +5 -0
- package/models/kb_setting.js +38 -3
- package/package.json +4 -3
- package/pubmodules/s/index.js +2 -2
- package/pubmodules/s/models/subscription-payment.js +2 -2
- package/pubmodules/s/stripe/index.js +2 -2
- package/routes/kb.js +952 -542
- package/routes/openai.js +3 -3
- package/routes/project.js +21 -6
- package/routes/quotes.js +13 -4
- package/services/QuoteManager.js +163 -16
- package/services/emailService.js +53 -1
- package/services/requestService.js +16 -5
- package/template/email/beenInvitedNewUser.html +221 -216
- package/template/email/checkpointReachedEmail.html +92 -0
- package/test/kbRoute.js +1186 -311
- package/test/mock/projectMock.js +2 -3
- package/test/openaiRoute.js +3 -0
- package/test/requestService.js +3 -0
- package/utils/aiUtils.js +41 -5
package/routes/openai.js
CHANGED
@@ -4,7 +4,7 @@ var { KBSettings } = require('../models/kb_setting');
|
|
4
4
|
var openaiService = require('../services/openaiService');
|
5
5
|
var winston = require('../config/winston');
|
6
6
|
const { QuoteManager } = require('../services/QuoteManager');
|
7
|
-
const {
|
7
|
+
const { MODELS_MULTIPLIER } = require('../utils/aiUtils');
|
8
8
|
|
9
9
|
router.post('/', async (req, res) => {
|
10
10
|
|
@@ -37,7 +37,7 @@ router.post('/', async (req, res) => {
|
|
37
37
|
if (usePublicKey === true) {
|
38
38
|
let isAvailable = await quoteManager.checkQuote(req.project, obj, 'tokens');
|
39
39
|
if (isAvailable === false) {
|
40
|
-
return res.status(403).send("Tokens quota exceeded")
|
40
|
+
return res.status(403).send({ success: false, message: "Tokens quota exceeded", error_code: 13001})
|
41
41
|
}
|
42
42
|
}
|
43
43
|
|
@@ -61,7 +61,7 @@ router.post('/', async (req, res) => {
|
|
61
61
|
json.messages.unshift(message);
|
62
62
|
}
|
63
63
|
|
64
|
-
let multiplier =
|
64
|
+
let multiplier = MODELS_MULTIPLIER[json.model];
|
65
65
|
if (!multiplier) {
|
66
66
|
multiplier = 1;
|
67
67
|
winston.info("No multiplier found for AI model")
|
package/routes/project.js
CHANGED
@@ -239,6 +239,7 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
|
|
239
239
|
winston.debug('UPDATE PROJECT REQ BODY ', req.body);
|
240
240
|
|
241
241
|
var update = {};
|
242
|
+
let updating_quotes = false;
|
242
243
|
|
243
244
|
if (req.body.profile) {
|
244
245
|
|
@@ -248,14 +249,22 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
|
|
248
249
|
|
249
250
|
winston.debug("Superadmin can modify the project profile")
|
250
251
|
update.profile = req.body.profile;
|
252
|
+
if (req.body.profile.quotes) {
|
253
|
+
updating_quotes = true;
|
254
|
+
}
|
251
255
|
|
252
|
-
|
253
|
-
|
256
|
+
/**
|
257
|
+
* Possibile Miglioramento
|
258
|
+
* Eliminare solo le chiavi di redis di notify solo per le quote che si stanno modificando.
|
259
|
+
* Per farlo è necessario permettere la modifica puntuale del project profile, attualmente non disponibile.
|
260
|
+
*/
|
254
261
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
262
|
+
delete req.user.attributes.isSuperadmin;
|
263
|
+
}
|
264
|
+
else {
|
265
|
+
winston.verbose("Project profile can't be modified by the current user " + req.user._id);
|
266
|
+
return res.status(403).send({ success: false, error: "You don't have the permission required to modify the project profile"});
|
267
|
+
}
|
259
268
|
|
260
269
|
// check if super admin
|
261
270
|
// let token = req.headers.authorization
|
@@ -457,6 +466,12 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
|
|
457
466
|
return res.status(500).send({ success: false, msg: 'Error updating object.' });
|
458
467
|
}
|
459
468
|
projectEvent.emit('project.update', updatedProject );
|
469
|
+
|
470
|
+
if (updating_quotes == true) {
|
471
|
+
let obj = { createdAt: new Date() };
|
472
|
+
let quoteManager = req.app.get('quote_manager');
|
473
|
+
quoteManager.invalidateCheckpointKeys(updatedProject, obj);
|
474
|
+
}
|
460
475
|
res.json(updatedProject);
|
461
476
|
});
|
462
477
|
});
|
package/routes/quotes.js
CHANGED
@@ -2,6 +2,7 @@ var express = require('express');
|
|
2
2
|
var router = express.Router();
|
3
3
|
const { QuoteManager } = require('../services/QuoteManager');
|
4
4
|
let winston = require('../config/winston');
|
5
|
+
const { MODELS_MULTIPLIER } = require('../utils/aiUtils');
|
5
6
|
|
6
7
|
|
7
8
|
router.post('/', async (req, res) => {
|
@@ -39,12 +40,20 @@ router.get('/:type', async (req, res) => {
|
|
39
40
|
router.post('/incr/:type', async (req, res) => {
|
40
41
|
|
41
42
|
let type = req.params.type;
|
42
|
-
let
|
43
|
-
body.createdAt = new Date();
|
43
|
+
let data = req.body;
|
44
44
|
|
45
45
|
let quoteManager = req.app.get('quote_manager');
|
46
|
-
|
47
|
-
let
|
46
|
+
|
47
|
+
let multiplier = MODELS_MULTIPLIER[data.model];
|
48
|
+
if (!multiplier) {
|
49
|
+
multiplier = 1;
|
50
|
+
winston.info("No multiplier found for AI model")
|
51
|
+
}
|
52
|
+
data.multiplier = multiplier;
|
53
|
+
data.createdAt = new Date();
|
54
|
+
|
55
|
+
let incremented_key = await quoteManager.incrementTokenCount(req.project, data);
|
56
|
+
let quote = await quoteManager.getCurrentQuote(req.project, data, type);
|
48
57
|
|
49
58
|
res.status(200).send({ message: "value incremented for key " + incremented_key, key: incremented_key, currentQuote: quote });
|
50
59
|
})
|
package/services/QuoteManager.js
CHANGED
@@ -4,12 +4,21 @@ const requestEvent = require('../event/requestEvent');
|
|
4
4
|
const messageEvent = require('../event/messageEvent');
|
5
5
|
const emailEvent = require('../event/emailEvent');
|
6
6
|
|
7
|
+
// NEW
|
8
|
+
// const PLANS_LIST = {
|
9
|
+
// FREE_TRIAL: { requests: 3000, messages: 0, tokens: 250000, email: 200, chatbots: 20, kbs: 50 }, // same as PREMIUM
|
10
|
+
// SANDBOX: { requests: 200, messages: 0, tokens: 100000, email: 200, chatbots: 2, kbs: 50 },
|
11
|
+
// BASIC: { requests: 1000, messages: 0, tokens: 2000000, email: 200, chatbots: 10, kbs: 200},
|
12
|
+
// PREMIUM: { requests: 3000, messages: 0, tokens: 5000000, email: 200, chatbots: 20, kbs: 500},
|
13
|
+
// CUSTOM: { requests: 3000, messages: 0, tokens: 5000000, email: 200, chatbots: 20, kbs: 500}
|
14
|
+
// }
|
15
|
+
|
7
16
|
const PLANS_LIST = {
|
8
|
-
FREE_TRIAL: { requests: 3000, messages: 0, tokens:
|
9
|
-
SANDBOX: { requests: 200, messages: 0, tokens:
|
10
|
-
BASIC: { requests: 800, messages: 0, tokens:
|
11
|
-
PREMIUM: { requests: 3000, messages: 0, tokens:
|
12
|
-
CUSTOM: { requests: 3000, messages: 0, tokens:
|
17
|
+
FREE_TRIAL: { requests: 3000, messages: 0, tokens: 5000000, email: 200, chatbots: 20, kbs: 50 }, // same as PREMIUM
|
18
|
+
SANDBOX: { requests: 200, messages: 0, tokens: 100000, email: 200, chatbots: 2, kbs: 50 },
|
19
|
+
BASIC: { requests: 800, messages: 0, tokens: 2000000, email: 200, chatbots: 5, kbs: 150},
|
20
|
+
PREMIUM: { requests: 3000, messages: 0, tokens: 5000000, email: 200, chatbots: 20, kbs: 300},
|
21
|
+
CUSTOM: { requests: 3000, messages: 0, tokens: 5000000, email: 200, chatbots: 20, kbs: 1000}
|
13
22
|
}
|
14
23
|
|
15
24
|
const typesList = ['requests', 'messages', 'email', 'tokens', 'chatbots', 'kbs']
|
@@ -41,6 +50,7 @@ class QuoteManager {
|
|
41
50
|
winston.verbose("[QuoteManager] incrementRequestsCount key: " + key);
|
42
51
|
|
43
52
|
await this.tdCache.incr(key)
|
53
|
+
this.sendEmailIfQuotaExceeded(project, request, 'requests', key);
|
44
54
|
return key;
|
45
55
|
}
|
46
56
|
|
@@ -61,6 +71,7 @@ class QuoteManager {
|
|
61
71
|
winston.verbose("[QuoteManager] incrementEmailCount key: " + key);
|
62
72
|
|
63
73
|
await this.tdCache.incr(key)
|
74
|
+
this.sendEmailIfQuotaExceeded(project, email, 'email', key);
|
64
75
|
return key;
|
65
76
|
}
|
66
77
|
|
@@ -78,7 +89,7 @@ class QuoteManager {
|
|
78
89
|
let tokens = data.tokens * data.multiplier;
|
79
90
|
await this.tdCache.incrbyfloat(key, tokens);
|
80
91
|
// await this.tdCache.incrby(key, tokens);
|
81
|
-
|
92
|
+
this.sendEmailIfQuotaExceeded(project, data, 'tokens', key);
|
82
93
|
return key;
|
83
94
|
}
|
84
95
|
// INCREMENT KEY SECTION - END
|
@@ -89,11 +100,22 @@ class QuoteManager {
|
|
89
100
|
winston.debug("generateKey object ", object)
|
90
101
|
winston.debug("generateKey type " + type)
|
91
102
|
let subscriptionDate;
|
92
|
-
|
93
|
-
|
103
|
+
|
104
|
+
if (this.project.isActiveSubscription === true) {
|
105
|
+
if (this.project.profile.subStart) {
|
106
|
+
subscriptionDate = this.project.profile.subStart;
|
107
|
+
} else {
|
108
|
+
// it should never happen
|
109
|
+
winston.error("Error: quote manager - isActiveSubscription is true but subStart does not exists.")
|
110
|
+
}
|
94
111
|
} else {
|
95
|
-
|
112
|
+
if (this.project.profile.subEnd) {
|
113
|
+
subscriptionDate = this.project.profile.subEnd;
|
114
|
+
} else {
|
115
|
+
subscriptionDate = this.project.createdAt;
|
116
|
+
}
|
96
117
|
}
|
118
|
+
|
97
119
|
let objectDate = object.createdAt;
|
98
120
|
winston.debug("objectDate " + objectDate);
|
99
121
|
|
@@ -124,7 +146,7 @@ class QuoteManager {
|
|
124
146
|
}
|
125
147
|
|
126
148
|
/**
|
127
|
-
* Get quotes for
|
149
|
+
* Get quotes for all types (tokens and request and ...)
|
128
150
|
*/
|
129
151
|
async getAllQuotes(project, obj) {
|
130
152
|
|
@@ -174,6 +196,124 @@ class QuoteManager {
|
|
174
196
|
}
|
175
197
|
}
|
176
198
|
|
199
|
+
async checkQuoteForAlert(project, object, type) {
|
200
|
+
|
201
|
+
if (quotes_enabled === false) {
|
202
|
+
winston.verbose("QUOTES DISABLED - checkQuote for type " + type);
|
203
|
+
return (null, null);
|
204
|
+
}
|
205
|
+
|
206
|
+
this.project = project;
|
207
|
+
let limits = await this.getPlanLimits();
|
208
|
+
winston.verbose("limits for current plan: ", limits)
|
209
|
+
|
210
|
+
let quote = await this.getCurrentQuote(project, object, type);
|
211
|
+
winston.verbose("getCurrentQuote resp: ", quote)
|
212
|
+
|
213
|
+
let data = {
|
214
|
+
limits: limits,
|
215
|
+
quote: quote
|
216
|
+
}
|
217
|
+
|
218
|
+
return data;
|
219
|
+
}
|
220
|
+
|
221
|
+
async sendEmailIfQuotaExceeded(project, object, type, key) {
|
222
|
+
|
223
|
+
let data = await this.checkQuoteForAlert(project, object, type);
|
224
|
+
let limits = data.limits;
|
225
|
+
let limit = data.limits[type];
|
226
|
+
let quote = data.quote;
|
227
|
+
|
228
|
+
const checkpoint = await this.percentageCalculator(limit, quote);
|
229
|
+
if (checkpoint == 0) {
|
230
|
+
return;
|
231
|
+
}
|
232
|
+
winston.verbose("checkpoint perc: ", checkpoint);
|
233
|
+
|
234
|
+
// Generate redis key
|
235
|
+
let nKey = key + ":notify:" + checkpoint;
|
236
|
+
let result = await this.tdCache.get(nKey);
|
237
|
+
if (!result) {
|
238
|
+
|
239
|
+
let allQuotes = await this.getAllQuotes(project, object);
|
240
|
+
let quotes = await this.generateQuotesObject(allQuotes, limits);
|
241
|
+
|
242
|
+
let data = {
|
243
|
+
id_project: project._id,
|
244
|
+
project_name: project.name,
|
245
|
+
type: type,
|
246
|
+
checkpoint: checkpoint,
|
247
|
+
quotes: quotes
|
248
|
+
}
|
249
|
+
|
250
|
+
emailEvent.emit('email.send.quote.checkpoint', data);
|
251
|
+
await this.tdCache.set(nKey, 'true', {EX: 2592000}); //seconds in one month = 2592000
|
252
|
+
} else {
|
253
|
+
winston.verbose("Quota checkpoint reached email already sent.")
|
254
|
+
}
|
255
|
+
|
256
|
+
}
|
257
|
+
|
258
|
+
async percentageCalculator(limit, quote) {
|
259
|
+
|
260
|
+
let p = (quote / limit) * 100;
|
261
|
+
|
262
|
+
if (p >= 100) { return 100; }
|
263
|
+
if (p >= 95) { return 95; }
|
264
|
+
if (p >= 75) { return 75; }
|
265
|
+
if (p >= 50) { return 50; }
|
266
|
+
|
267
|
+
return 0;
|
268
|
+
|
269
|
+
}
|
270
|
+
|
271
|
+
async invalidateCheckpointKeys(project, obj) {
|
272
|
+
|
273
|
+
this.project = project;
|
274
|
+
winston.verbose("invalidateCheckpointKeys project " + project._id);
|
275
|
+
let requests_key = await this.generateKey(obj, 'requests');
|
276
|
+
let tokens_key = await this.generateKey(obj, 'tokens');
|
277
|
+
let email_key = await this.generateKey(obj, 'email');
|
278
|
+
|
279
|
+
let checkpoints = ['50', '75', '95', '100']
|
280
|
+
|
281
|
+
checkpoints.forEach( async (checkpoint) => {
|
282
|
+
let nrequests_key = requests_key + ":notify:" + checkpoint;
|
283
|
+
let ntokens_key = tokens_key + ":notify:" + checkpoint;
|
284
|
+
let nemail_key = email_key + ":notify:" + checkpoint;
|
285
|
+
|
286
|
+
winston.verbose("invalidateCheckpointKeys nrequests_key: " + nrequests_key);
|
287
|
+
winston.verbose("invalidateCheckpointKeys ntokens_key: " + ntokens_key);
|
288
|
+
winston.verbose("invalidateCheckpointKeys nemail_key: " + nemail_key);
|
289
|
+
|
290
|
+
this.tdCache.del(nrequests_key);
|
291
|
+
this.tdCache.del(ntokens_key);
|
292
|
+
this.tdCache.del(nemail_key);
|
293
|
+
|
294
|
+
return true;
|
295
|
+
})
|
296
|
+
|
297
|
+
}
|
298
|
+
|
299
|
+
async generateQuotesObject(quotes, limits) {
|
300
|
+
let quotes_obj = {
|
301
|
+
requests: {
|
302
|
+
quote: quotes.requests.quote,
|
303
|
+
perc: ((quotes.requests.quote / limits['requests']) * 100).toFixed(1)
|
304
|
+
},
|
305
|
+
tokens: {
|
306
|
+
quote: quotes.tokens.quote,
|
307
|
+
perc: ((quotes.tokens.quote / limits['tokens']) * 100).toFixed(1)
|
308
|
+
},
|
309
|
+
email: {
|
310
|
+
quote: quotes.email.quote,
|
311
|
+
perc: ((quotes.email.quote / limits['email']) * 100).toFixed(1)
|
312
|
+
}
|
313
|
+
}
|
314
|
+
return quotes_obj
|
315
|
+
}
|
316
|
+
|
177
317
|
|
178
318
|
async getPlanLimits(project) {
|
179
319
|
|
@@ -182,13 +322,11 @@ class QuoteManager {
|
|
182
322
|
};
|
183
323
|
|
184
324
|
let limits;
|
325
|
+
const plan = this.project.profile.name;
|
326
|
+
|
185
327
|
if (this.project.profile.type === 'payment') {
|
186
328
|
|
187
|
-
const plan = this.project.profile.name;
|
188
329
|
switch (plan) {
|
189
|
-
case 'Sandbox':
|
190
|
-
limits = PLANS_LIST.SANDBOX;
|
191
|
-
break;
|
192
330
|
case 'Basic':
|
193
331
|
limits = PLANS_LIST.BASIC;
|
194
332
|
break;
|
@@ -211,14 +349,21 @@ class QuoteManager {
|
|
211
349
|
limits = PLANS_LIST.FREE_TRIAL;
|
212
350
|
}
|
213
351
|
} else {
|
214
|
-
limits = PLANS_LIST.FREE_TRIAL;
|
215
|
-
}
|
216
352
|
|
353
|
+
if (this.project.trialExpired === false) {
|
354
|
+
limits = PLANS_LIST.FREE_TRIAL
|
355
|
+
} else {
|
356
|
+
limits = PLANS_LIST.SANDBOX;
|
357
|
+
}
|
358
|
+
|
359
|
+
}
|
217
360
|
if (this.project?.profile?.quotes) {
|
218
361
|
let profile_quotes = this.project?.profile?.quotes;
|
219
362
|
const merged_quotes = Object.assign({}, limits, profile_quotes);
|
363
|
+
winston.verbose("Custom Limits: ", limits)
|
220
364
|
return merged_quotes;
|
221
365
|
} else {
|
366
|
+
winston.verbose("Default Limits: ", limits)
|
222
367
|
return limits;
|
223
368
|
}
|
224
369
|
}
|
@@ -256,6 +401,8 @@ class QuoteManager {
|
|
256
401
|
if (quotes_enabled === true) {
|
257
402
|
winston.verbose("request.create.quote event catched");
|
258
403
|
let result = await this.incrementRequestsCount(payload.project, payload.request);
|
404
|
+
|
405
|
+
|
259
406
|
return result;
|
260
407
|
} else {
|
261
408
|
winston.verbose("QUOTES DISABLED - request.create.quote event")
|
package/services/emailService.js
CHANGED
@@ -149,7 +149,6 @@ class EmailService {
|
|
149
149
|
var that = this;
|
150
150
|
winston.debug('EmailService readTemplate: ' + templateName + ' environmentVariableKey: ' + environmentVariableKey + ' setting ' + JSON.stringify(settings));
|
151
151
|
|
152
|
-
|
153
152
|
if (settings && settings.email && settings.email.templates) {
|
154
153
|
|
155
154
|
var templates = settings.email.templates;
|
@@ -168,6 +167,21 @@ class EmailService {
|
|
168
167
|
return resolve(template);
|
169
168
|
});
|
170
169
|
}
|
170
|
+
else {
|
171
|
+
var envTemplate = process.env[environmentVariableKey];
|
172
|
+
winston.debug('EmailService envTemplate: ' + envTemplate);
|
173
|
+
|
174
|
+
if (envTemplate) {
|
175
|
+
winston.debug('EmailService return envTemplate: ' + envTemplate);
|
176
|
+
|
177
|
+
return envTemplate;
|
178
|
+
} else {
|
179
|
+
winston.debug('EmailService return file: ' + templateName);
|
180
|
+
|
181
|
+
return that.readTemplateFile(templateName);
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
171
185
|
// else {
|
172
186
|
// return that.readTemplateFile(templateName);
|
173
187
|
// }
|
@@ -1816,6 +1830,44 @@ class EmailService {
|
|
1816
1830
|
|
1817
1831
|
}
|
1818
1832
|
|
1833
|
+
async sendEmailQuotaCheckpointReached(to, firstname, project_name, resource_name, checkpoint, quotes) {
|
1834
|
+
|
1835
|
+
winston.info("sendEmailQuotaCheckpointReached: " + to);
|
1836
|
+
|
1837
|
+
var that = this;
|
1838
|
+
|
1839
|
+
let html = await this.readTemplate('checkpointReachedEmail.html', undefined, "EMAIL_QUOTA_CHECKPOINT_REACHED");
|
1840
|
+
winston.debug("html: " + html);
|
1841
|
+
|
1842
|
+
let template = handlebars.compile(html);
|
1843
|
+
|
1844
|
+
let requests_quote = quotes.requests.quote;
|
1845
|
+
let requests_perc = quotes.requests.perc;
|
1846
|
+
|
1847
|
+
let tokens_quote = quotes.tokens.quote;
|
1848
|
+
let tokens_perc = quotes.tokens.perc;
|
1849
|
+
|
1850
|
+
let email_quote = quotes.email.quote;
|
1851
|
+
let email_perc = quotes.email.perc;
|
1852
|
+
|
1853
|
+
let replacements = {
|
1854
|
+
firstname: firstname,
|
1855
|
+
project_name: project_name,
|
1856
|
+
resource_name: resource_name,
|
1857
|
+
checkpoint: checkpoint,
|
1858
|
+
requests_quote: requests_quote,
|
1859
|
+
requests_perc: requests_perc,
|
1860
|
+
tokens_quote: tokens_quote,
|
1861
|
+
tokens_perc: tokens_perc,
|
1862
|
+
email_quote: email_quote,
|
1863
|
+
email_perc: email_perc
|
1864
|
+
}
|
1865
|
+
|
1866
|
+
html = template(replacements);
|
1867
|
+
|
1868
|
+
that.send({ to: to, subject: "Update on resources usage", html: html });
|
1869
|
+
}
|
1870
|
+
|
1819
1871
|
parseText(text, payload) {
|
1820
1872
|
|
1821
1873
|
|
@@ -525,6 +525,8 @@ class RequestService {
|
|
525
525
|
|
526
526
|
}
|
527
527
|
|
528
|
+
let isTestConversation = false;
|
529
|
+
|
528
530
|
var that = this;
|
529
531
|
|
530
532
|
return new Promise(async (resolve, reject) => {
|
@@ -548,10 +550,16 @@ class RequestService {
|
|
548
550
|
request: request
|
549
551
|
}
|
550
552
|
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
553
|
+
if (attributes && attributes.sourcePage && (attributes.sourcePage.indexOf("td_draft=true") > -1)) {
|
554
|
+
winston.verbose("is a test conversation --> skip quote availability check")
|
555
|
+
isTestConversation = true;
|
556
|
+
}
|
557
|
+
else {
|
558
|
+
let available = await qm.checkQuote(p, request, 'requests');
|
559
|
+
if (available === false) {
|
560
|
+
winston.info("Requests limits reached for project " + p._id)
|
561
|
+
return false;
|
562
|
+
}
|
555
563
|
}
|
556
564
|
|
557
565
|
|
@@ -717,7 +725,10 @@ class RequestService {
|
|
717
725
|
winston.verbose("Performance Request created in millis: " + endDate - startDate);
|
718
726
|
|
719
727
|
requestEvent.emit('request.create.simple', savedRequest);
|
720
|
-
|
728
|
+
|
729
|
+
if (!isTestConversation) {
|
730
|
+
requestEvent.emit('request.create.quote', payload);;
|
731
|
+
}
|
721
732
|
|
722
733
|
return resolve(savedRequest);
|
723
734
|
|