rez_core 3.1.86 → 3.1.88
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/dist/module/integration/controller/integration.controller.d.ts +9 -1
- package/dist/module/integration/controller/integration.controller.js +21 -0
- package/dist/module/integration/controller/integration.controller.js.map +1 -1
- package/dist/module/integration/dto/create-config.dto.d.ts +6 -0
- package/dist/module/integration/dto/create-config.dto.js +24 -1
- package/dist/module/integration/dto/create-config.dto.js.map +1 -1
- package/dist/module/integration/service/integration.service.d.ts +8 -0
- package/dist/module/integration/service/integration.service.js +27 -1
- package/dist/module/integration/service/integration.service.js.map +1 -1
- package/dist/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.d.ts +13 -2
- package/dist/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.js +66 -112
- package/dist/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.js.map +1 -1
- package/dist/module/mapper/controller/field-mapper.controller.d.ts +1 -1
- package/dist/module/mapper/service/field-mapper.service.d.ts +1 -1
- package/dist/module/mapper/service/field-mapper.service.js +6 -1
- package/dist/module/mapper/service/field-mapper.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/integration/controller/integration.controller.ts +21 -0
- package/src/module/integration/dto/create-config.dto.ts +18 -0
- package/src/module/integration/service/integration.service.ts +61 -3
- package/src/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.ts +97 -155
- package/src/module/mapper/service/field-mapper.service.ts +6 -1
package/package.json
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
CreateConfigDto,
|
|
20
20
|
CreateUserIntegrationDto,
|
|
21
21
|
GenericSendMessageDto,
|
|
22
|
+
GetIntegrationTemplatesDto,
|
|
22
23
|
SendGridTemplatesDto,
|
|
23
24
|
SendGridVerifiedSendersDto,
|
|
24
25
|
UpdateConfigDto,
|
|
@@ -327,6 +328,26 @@ export class IntegrationController {
|
|
|
327
328
|
}
|
|
328
329
|
}
|
|
329
330
|
|
|
331
|
+
@Post('templates')
|
|
332
|
+
@HttpCode(HttpStatus.OK)
|
|
333
|
+
async getIntegrationTemplates(@Body() dto: GetIntegrationTemplatesDto) {
|
|
334
|
+
try {
|
|
335
|
+
return await this.integrationService.getIntegrationTemplates(
|
|
336
|
+
dto.levelId,
|
|
337
|
+
dto.levelType,
|
|
338
|
+
dto.app_code,
|
|
339
|
+
dto.integration_type,
|
|
340
|
+
);
|
|
341
|
+
} catch (error) {
|
|
342
|
+
throw new BadRequestException({
|
|
343
|
+
success: false,
|
|
344
|
+
error: 'GET_TEMPLATES_ERROR',
|
|
345
|
+
message: error.message || 'Failed to get templates',
|
|
346
|
+
code: 'INTEGRATION_TEMPLATES_ERROR',
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
330
351
|
@Post('config/delete/:configId')
|
|
331
352
|
@HttpCode(HttpStatus.OK)
|
|
332
353
|
async disconnectConfig(@Param('configId', ParseIntPipe) configId: number) {
|
|
@@ -360,6 +360,24 @@ export class SendGridTemplatesDto {
|
|
|
360
360
|
app_code: string;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
export class GetIntegrationTemplatesDto {
|
|
364
|
+
@IsNotEmpty()
|
|
365
|
+
@IsNumber()
|
|
366
|
+
levelId: number;
|
|
367
|
+
|
|
368
|
+
@IsNotEmpty()
|
|
369
|
+
@IsString()
|
|
370
|
+
levelType: string;
|
|
371
|
+
|
|
372
|
+
@IsNotEmpty()
|
|
373
|
+
@IsString()
|
|
374
|
+
app_code: string;
|
|
375
|
+
|
|
376
|
+
@IsNotEmpty()
|
|
377
|
+
@IsString()
|
|
378
|
+
integration_type: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE';
|
|
379
|
+
}
|
|
380
|
+
|
|
363
381
|
export class VerifiedSenderDto {
|
|
364
382
|
@IsString()
|
|
365
383
|
label: string;
|
|
@@ -1000,7 +1000,7 @@ export class IntegrationService {
|
|
|
1000
1000
|
let variables;
|
|
1001
1001
|
let externalTemplateId: string | undefined = undefined;
|
|
1002
1002
|
let richText;
|
|
1003
|
-
if (templateId
|
|
1003
|
+
if (templateId) {
|
|
1004
1004
|
const templateData = await this.processTemplate(
|
|
1005
1005
|
parseInt(templateId, 10),
|
|
1006
1006
|
entity_type,
|
|
@@ -1255,8 +1255,8 @@ export class IntegrationService {
|
|
|
1255
1255
|
|
|
1256
1256
|
private async processTemplate(
|
|
1257
1257
|
templateId: number,
|
|
1258
|
-
entity_type:
|
|
1259
|
-
entity_id:
|
|
1258
|
+
entity_type: any,
|
|
1259
|
+
entity_id: any,
|
|
1260
1260
|
): Promise<{ variables?: Record<string, any>; externalTemplateId?: string; rich_text?: string }> {
|
|
1261
1261
|
const commTemplate: any = await this.entityService.getEntityData(COMM_TEMPLATE, templateId, {} as any);
|
|
1262
1262
|
if (!commTemplate) {
|
|
@@ -2019,6 +2019,64 @@ export class IntegrationService {
|
|
|
2019
2019
|
}
|
|
2020
2020
|
}
|
|
2021
2021
|
|
|
2022
|
+
async getIntegrationTemplates(
|
|
2023
|
+
levelId: number,
|
|
2024
|
+
levelType: string,
|
|
2025
|
+
app_code: string,
|
|
2026
|
+
integration_type: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE',
|
|
2027
|
+
): Promise<{
|
|
2028
|
+
success: boolean;
|
|
2029
|
+
data?: Array<{
|
|
2030
|
+
label: string;
|
|
2031
|
+
value: string;
|
|
2032
|
+
}>;
|
|
2033
|
+
error?: string;
|
|
2034
|
+
}> {
|
|
2035
|
+
try {
|
|
2036
|
+
// Get active configuration for the integration type
|
|
2037
|
+
const config = await this.getSingleActiveConfig(
|
|
2038
|
+
levelId,
|
|
2039
|
+
levelType,
|
|
2040
|
+
app_code,
|
|
2041
|
+
integration_type,
|
|
2042
|
+
);
|
|
2043
|
+
|
|
2044
|
+
if (!config) {
|
|
2045
|
+
return {
|
|
2046
|
+
success: false,
|
|
2047
|
+
error: `No active ${integration_type} configuration found for this level`,
|
|
2048
|
+
};
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
// Create strategy instance
|
|
2052
|
+
const strategy = this.integrationFactory.create(
|
|
2053
|
+
config.integration_type,
|
|
2054
|
+
'API',
|
|
2055
|
+
config.integration_provider,
|
|
2056
|
+
);
|
|
2057
|
+
|
|
2058
|
+
// Check if strategy supports getTemplates
|
|
2059
|
+
if (typeof (strategy as any).getTemplates !== 'function') {
|
|
2060
|
+
return {
|
|
2061
|
+
success: false,
|
|
2062
|
+
error: `Template retrieval not supported for provider: ${config.integration_provider}`,
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
// Call getTemplates method
|
|
2067
|
+
return await (strategy as any).getTemplates(config.config_json);
|
|
2068
|
+
} catch (error) {
|
|
2069
|
+
this.logger.error(
|
|
2070
|
+
`Error fetching templates for ${integration_type} level ${levelId}/${levelType}:`,
|
|
2071
|
+
error.message,
|
|
2072
|
+
);
|
|
2073
|
+
return {
|
|
2074
|
+
success: false,
|
|
2075
|
+
error: `Failed to fetch templates: ${error.message}`,
|
|
2076
|
+
};
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2022
2080
|
async getSendGridTemplates(
|
|
2023
2081
|
levelId: number,
|
|
2024
2082
|
levelType: string,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Injectable, Logger } from '@nestjs/common';
|
|
2
2
|
import axios, { AxiosResponse } from 'axios';
|
|
3
|
+
import { randomUUID } from 'crypto';
|
|
3
4
|
import {
|
|
4
5
|
IntegrationResult,
|
|
5
6
|
IntegrationStrategy,
|
|
@@ -9,19 +10,12 @@ interface TubelightWhatsAppConfig {
|
|
|
9
10
|
userName: string;
|
|
10
11
|
password: string;
|
|
11
12
|
tenantId: string;
|
|
13
|
+
custUuid?: string;
|
|
12
14
|
baseUrl?: string;
|
|
13
|
-
sourceNumber?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface TubelightMessage {
|
|
17
|
-
to: string;
|
|
18
|
-
message: string;
|
|
19
|
-
messageType?: string;
|
|
20
|
-
mediaUrl?: string;
|
|
21
|
-
caption?: string;
|
|
22
|
-
filename?: string;
|
|
23
15
|
templateId?: string;
|
|
24
|
-
|
|
16
|
+
templateName?: string;
|
|
17
|
+
templateLanguage?: string;
|
|
18
|
+
variables?: string;
|
|
25
19
|
}
|
|
26
20
|
|
|
27
21
|
interface TubelightApiResponse {
|
|
@@ -38,7 +32,7 @@ interface TubelightApiResponse {
|
|
|
38
32
|
export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
39
33
|
private readonly logger = new Logger(TubelightWhatsAppStrategy.name);
|
|
40
34
|
private readonly defaultBaseUrl =
|
|
41
|
-
|
|
35
|
+
'https://portal.tubelightcommunications.com/whatsapp/api/v1';
|
|
42
36
|
|
|
43
37
|
async sendMessage(
|
|
44
38
|
to: string,
|
|
@@ -58,16 +52,15 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
58
52
|
}
|
|
59
53
|
|
|
60
54
|
const baseUrl = tubelightConfig.baseUrl || this.defaultBaseUrl;
|
|
61
|
-
const url = `${baseUrl}/
|
|
55
|
+
const url = `${baseUrl}/bulk/send`;
|
|
62
56
|
|
|
63
|
-
const payload = this.prepareMessagePayload(to, message, config);
|
|
57
|
+
const payload = [this.prepareMessagePayload(to, message, config)];
|
|
64
58
|
|
|
65
59
|
const response: AxiosResponse<TubelightApiResponse> = await axios.post(
|
|
66
60
|
url,
|
|
67
61
|
payload,
|
|
68
62
|
{
|
|
69
63
|
headers: {
|
|
70
|
-
'X-TENANT-ID': tubelightConfig.tenantId,
|
|
71
64
|
'Content-Type': 'application/json',
|
|
72
65
|
Authorization: `Bearer ${token}`,
|
|
73
66
|
},
|
|
@@ -76,8 +69,7 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
76
69
|
);
|
|
77
70
|
|
|
78
71
|
if (
|
|
79
|
-
response.
|
|
80
|
-
(response.data?.messageId || response.data?.id)
|
|
72
|
+
response.status === 200
|
|
81
73
|
) {
|
|
82
74
|
const messageId = response.data.messageId || response.data.id;
|
|
83
75
|
this.logger.log(
|
|
@@ -166,98 +158,55 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
166
158
|
|
|
167
159
|
private prepareMessagePayload(to: string, message: string, config: any): any {
|
|
168
160
|
const basePayload = {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
161
|
+
cust_uuid: config.custUuid || randomUUID(),
|
|
162
|
+
to: [this.formatPhoneNumber(to)],
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// If templateId exists, send template message
|
|
166
|
+
if (config.templateId || config.templateName) {
|
|
167
|
+
const messagePayload: any = {
|
|
168
|
+
type: 'template',
|
|
169
|
+
template_name: config.templateId || config.templateName,
|
|
170
|
+
language: config.templateLanguage || 'en',
|
|
171
|
+
};
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
mediaUrl: config.mediaUrl,
|
|
190
|
-
caption: message || config.caption || '',
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
case 'document':
|
|
194
|
-
return {
|
|
195
|
-
...basePayload,
|
|
196
|
-
messageType: 'DOCUMENT',
|
|
197
|
-
mediaUrl: config.mediaUrl,
|
|
198
|
-
filename: config.filename || 'document',
|
|
199
|
-
caption: message || config.caption || '',
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
case 'audio':
|
|
203
|
-
return {
|
|
204
|
-
...basePayload,
|
|
205
|
-
messageType: 'AUDIO',
|
|
206
|
-
mediaUrl: config.mediaUrl,
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
case 'video':
|
|
210
|
-
return {
|
|
211
|
-
...basePayload,
|
|
212
|
-
messageType: 'VIDEO',
|
|
213
|
-
mediaUrl: config.mediaUrl,
|
|
214
|
-
caption: message || config.caption || '',
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
case 'location':
|
|
218
|
-
return {
|
|
219
|
-
...basePayload,
|
|
220
|
-
messageType: 'LOCATION',
|
|
221
|
-
latitude: config.latitude,
|
|
222
|
-
longitude: config.longitude,
|
|
223
|
-
name: config.locationName || '',
|
|
224
|
-
address: config.locationAddress || '',
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
case 'interactive':
|
|
228
|
-
return {
|
|
229
|
-
...basePayload,
|
|
230
|
-
messageType: 'INTERACTIVE',
|
|
231
|
-
interactiveType: config.interactiveType || 'button',
|
|
232
|
-
text: message,
|
|
233
|
-
buttons: config.buttons || [],
|
|
234
|
-
sections: config.sections || [],
|
|
235
|
-
header: config.header,
|
|
236
|
-
footer: config.footer,
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
default:
|
|
240
|
-
// Fall back to text message
|
|
241
|
-
break;
|
|
173
|
+
// Add body_params if provided
|
|
174
|
+
if (config.variables) {
|
|
175
|
+
try {
|
|
176
|
+
// Parse JSON string
|
|
177
|
+
const parsedVariables = typeof config.variables === 'string'
|
|
178
|
+
? JSON.parse(config.variables)
|
|
179
|
+
: config.variables;
|
|
180
|
+
|
|
181
|
+
// Convert object to array of values, or use array as-is
|
|
182
|
+
messagePayload.body_params = Array.isArray(parsedVariables)
|
|
183
|
+
? parsedVariables
|
|
184
|
+
: Object.values(parsedVariables);
|
|
185
|
+
} catch (e) {
|
|
186
|
+
this.logger.error('Failed to parse variables JSON:', e.message);
|
|
187
|
+
messagePayload.body_params = [];
|
|
188
|
+
}
|
|
242
189
|
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
...basePayload,
|
|
193
|
+
message: messagePayload,
|
|
194
|
+
};
|
|
243
195
|
}
|
|
244
196
|
|
|
245
197
|
// Default text message
|
|
246
198
|
return {
|
|
247
199
|
...basePayload,
|
|
248
|
-
|
|
249
|
-
|
|
200
|
+
message: {
|
|
201
|
+
type: 'text',
|
|
202
|
+
text: message,
|
|
203
|
+
},
|
|
250
204
|
};
|
|
251
205
|
}
|
|
252
206
|
|
|
253
207
|
private formatPhoneNumber(phoneNumber: string): string {
|
|
254
|
-
// Remove any non-digit characters
|
|
255
|
-
let formatted = phoneNumber.replace(/
|
|
256
|
-
|
|
257
|
-
// If it doesn't start with +, assume it needs country code
|
|
258
|
-
if (!formatted.startsWith('+')) {
|
|
259
|
-
formatted = `+${formatted}`;
|
|
260
|
-
}
|
|
208
|
+
// Remove any non-digit characters
|
|
209
|
+
let formatted = phoneNumber.replace(/\D/g, '');
|
|
261
210
|
|
|
262
211
|
return formatted;
|
|
263
212
|
}
|
|
@@ -292,46 +241,6 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
292
241
|
return false;
|
|
293
242
|
}
|
|
294
243
|
|
|
295
|
-
// Validate message type specific requirements
|
|
296
|
-
if (config.messageType) {
|
|
297
|
-
switch (config.messageType) {
|
|
298
|
-
case 'template':
|
|
299
|
-
if (!config.templateId) {
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
break;
|
|
303
|
-
|
|
304
|
-
case 'image':
|
|
305
|
-
case 'document':
|
|
306
|
-
case 'audio':
|
|
307
|
-
case 'video':
|
|
308
|
-
if (!config.mediaUrl) {
|
|
309
|
-
return false;
|
|
310
|
-
}
|
|
311
|
-
break;
|
|
312
|
-
|
|
313
|
-
case 'location':
|
|
314
|
-
if (
|
|
315
|
-
typeof config.latitude !== 'number' ||
|
|
316
|
-
typeof config.longitude !== 'number'
|
|
317
|
-
) {
|
|
318
|
-
return false;
|
|
319
|
-
}
|
|
320
|
-
break;
|
|
321
|
-
|
|
322
|
-
case 'interactive':
|
|
323
|
-
if (
|
|
324
|
-
!config.buttons &&
|
|
325
|
-
!config.sections &&
|
|
326
|
-
(!config.interactiveType ||
|
|
327
|
-
!['button', 'list'].includes(config.interactiveType))
|
|
328
|
-
) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
break;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
244
|
return true;
|
|
336
245
|
}
|
|
337
246
|
|
|
@@ -347,7 +256,6 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
347
256
|
|
|
348
257
|
const response = await axios.get(url, {
|
|
349
258
|
headers: {
|
|
350
|
-
'X-TENANT-ID': config.tenantId,
|
|
351
259
|
Authorization: `Bearer ${token}`,
|
|
352
260
|
},
|
|
353
261
|
});
|
|
@@ -364,7 +272,14 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
364
272
|
}
|
|
365
273
|
}
|
|
366
274
|
|
|
367
|
-
async getTemplates(config: TubelightWhatsAppConfig): Promise<
|
|
275
|
+
async getTemplates(config: TubelightWhatsAppConfig): Promise<{
|
|
276
|
+
success: boolean;
|
|
277
|
+
data?: Array<{
|
|
278
|
+
label: string;
|
|
279
|
+
value: string;
|
|
280
|
+
}>;
|
|
281
|
+
error?: string;
|
|
282
|
+
}> {
|
|
368
283
|
try {
|
|
369
284
|
const token = await this.authenticate(config);
|
|
370
285
|
if (!token) {
|
|
@@ -372,24 +287,52 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
372
287
|
}
|
|
373
288
|
|
|
374
289
|
const baseUrl = config.baseUrl || this.defaultBaseUrl;
|
|
375
|
-
const url = `${baseUrl}/
|
|
290
|
+
const url = `${baseUrl}/retreive/template`;
|
|
376
291
|
|
|
377
|
-
const response = await axios.
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
292
|
+
const response = await axios.post(
|
|
293
|
+
url,
|
|
294
|
+
{},
|
|
295
|
+
{
|
|
296
|
+
headers: {
|
|
297
|
+
'Content-Type': 'application/json',
|
|
298
|
+
Authorization: `Bearer ${token}`,
|
|
299
|
+
},
|
|
381
300
|
},
|
|
382
|
-
|
|
301
|
+
);
|
|
383
302
|
|
|
384
|
-
|
|
303
|
+
const templates = response.data?.data || response.data?.templates || response.data || [];
|
|
304
|
+
|
|
305
|
+
// Format the response with templateName as both label and value
|
|
306
|
+
const formattedTemplates = Array.isArray(templates)
|
|
307
|
+
? templates.map((template: any) => ({
|
|
308
|
+
label: template.templateName,
|
|
309
|
+
value: template.templateName,
|
|
310
|
+
}))
|
|
311
|
+
: [];
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
success: true,
|
|
315
|
+
data: formattedTemplates,
|
|
316
|
+
};
|
|
385
317
|
} catch (error) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
)
|
|
318
|
+
let errorMessage = 'Failed to fetch Tubelight templates';
|
|
319
|
+
|
|
320
|
+
if (error.response?.status === 401) {
|
|
321
|
+
errorMessage = 'Authentication failed';
|
|
322
|
+
} else if (error.response?.data?.message) {
|
|
323
|
+
errorMessage = error.response.data.message;
|
|
324
|
+
} else if (error.response?.data?.error) {
|
|
325
|
+
errorMessage = error.response.data.error;
|
|
326
|
+
} else if (error.message) {
|
|
327
|
+
errorMessage = error.message;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
this.logger.error('Failed to get Tubelight templates', errorMessage);
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
success: false,
|
|
334
|
+
error: errorMessage,
|
|
335
|
+
};
|
|
393
336
|
}
|
|
394
337
|
}
|
|
395
338
|
|
|
@@ -408,7 +351,6 @@ export class TubelightWhatsAppStrategy implements IntegrationStrategy {
|
|
|
408
351
|
|
|
409
352
|
const response = await axios.get(url, {
|
|
410
353
|
headers: {
|
|
411
|
-
'X-TENANT-ID': config.tenantId,
|
|
412
354
|
Authorization: `Bearer ${token}`,
|
|
413
355
|
},
|
|
414
356
|
});
|
|
@@ -65,7 +65,12 @@ export class FieldMapperService extends EntityServiceImpl {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
async getMapperFields(mapperId: number) {
|
|
68
|
-
|
|
68
|
+
let fieldMappers = await this.fieldMapperRepository.findByMapperId(mapperId);
|
|
69
|
+
const fieldMapperDtos = fieldMappers as unknown as FieldMapperDto[];
|
|
70
|
+
for(const fieldMapper of fieldMapperDtos) {
|
|
71
|
+
fieldMapper.field_lovs = await this.fieldLovsRepository.findByMapperFieldId(fieldMapper.id);
|
|
72
|
+
}
|
|
73
|
+
return fieldMapperDtos;
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
async getFieldLovs(mapperFieldId: number) {
|