rez_core 5.0.145 → 5.0.150

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.
Files changed (62) hide show
  1. package/dist/config/bull.config.js +4 -4
  2. package/dist/config/bull.config.js.map +1 -1
  3. package/dist/migrations/1732612800000-AddEntityJsonGinIndex.d.ts +6 -0
  4. package/dist/migrations/1732612800000-AddEntityJsonGinIndex.js +32 -0
  5. package/dist/migrations/1732612800000-AddEntityJsonGinIndex.js.map +1 -0
  6. package/dist/module/entity_json/entity_json.module.js +1 -1
  7. package/dist/module/entity_json/entity_json.module.js.map +1 -1
  8. package/dist/module/entity_json/service/entity_json.service.js +1 -1
  9. package/dist/module/entity_json/service/entity_json.service.js.map +1 -1
  10. package/dist/module/filter/controller/filter.controller.d.ts +12 -0
  11. package/dist/module/filter/controller/filter.controller.js +1 -1
  12. package/dist/module/filter/controller/filter.controller.js.map +1 -1
  13. package/dist/module/filter/filter.module.js +9 -2
  14. package/dist/module/filter/filter.module.js.map +1 -1
  15. package/dist/module/filter/repository/saved-filter.repository.d.ts +5 -1
  16. package/dist/module/filter/repository/saved-filter.repository.js +5 -1
  17. package/dist/module/filter/repository/saved-filter.repository.js.map +1 -1
  18. package/dist/module/filter/service/filter.service.d.ts +37 -1
  19. package/dist/module/filter/service/filter.service.js +30 -2
  20. package/dist/module/filter/service/filter.service.js.map +1 -1
  21. package/dist/module/filter/service/flatjson-filter.service.d.ts +30 -0
  22. package/dist/module/filter/service/flatjson-filter.service.js +615 -0
  23. package/dist/module/filter/service/flatjson-filter.service.js.map +1 -0
  24. package/dist/module/integration/service/wrapper.service.d.ts +1 -3
  25. package/dist/module/integration/service/wrapper.service.js +2 -24
  26. package/dist/module/integration/service/wrapper.service.js.map +1 -1
  27. package/dist/module/linked_attributes/controller/linked_attributes.controller.d.ts +19 -0
  28. package/dist/module/linked_attributes/controller/linked_attributes.controller.js +77 -0
  29. package/dist/module/linked_attributes/controller/linked_attributes.controller.js.map +1 -1
  30. package/dist/module/linked_attributes/dto/create-linked-attribute-smart.dto.d.ts +13 -0
  31. package/dist/module/linked_attributes/dto/create-linked-attribute-smart.dto.js +64 -0
  32. package/dist/module/linked_attributes/dto/create-linked-attribute-smart.dto.js.map +1 -0
  33. package/dist/module/linked_attributes/linked_attributes.module.js +8 -1
  34. package/dist/module/linked_attributes/linked_attributes.module.js.map +1 -1
  35. package/dist/module/linked_attributes/service/linked_attributes.service.d.ts +41 -1
  36. package/dist/module/linked_attributes/service/linked_attributes.service.js +266 -2
  37. package/dist/module/linked_attributes/service/linked_attributes.service.js.map +1 -1
  38. package/dist/module/meta/dto/entity-table.dto.d.ts +4 -1
  39. package/dist/module/meta/dto/entity-table.dto.js.map +1 -1
  40. package/dist/module/meta/service/media-data.service.js +5 -18
  41. package/dist/module/meta/service/media-data.service.js.map +1 -1
  42. package/dist/tsconfig.build.tsbuildinfo +1 -1
  43. package/package.json +1 -1
  44. package/src/config/bull.config.ts +4 -4
  45. package/src/migrations/1732612800000-AddEntityJsonGinIndex.ts +41 -0
  46. package/src/module/entity_json/docs/FlatJson_Filterin_System.md +2804 -0
  47. package/src/module/entity_json/entity_json.module.ts +1 -1
  48. package/src/module/entity_json/service/entity_json.service.ts +1 -1
  49. package/src/module/filter/controller/filter.controller.ts +1 -3
  50. package/src/module/filter/filter.module.ts +9 -2
  51. package/src/module/filter/repository/saved-filter.repository.ts +5 -8
  52. package/src/module/filter/service/filter.service.ts +49 -0
  53. package/src/module/filter/service/flatjson-filter.service.ts +888 -0
  54. package/src/module/filter/test/flatjson-filter.service.spec.ts +415 -0
  55. package/src/module/integration/service/wrapper.service.ts +0 -37
  56. package/src/module/linked_attributes/controller/linked_attributes.controller.ts +86 -0
  57. package/src/module/linked_attributes/dto/create-linked-attribute-smart.dto.ts +54 -0
  58. package/src/module/linked_attributes/linked_attributes.module.ts +9 -2
  59. package/src/module/linked_attributes/service/linked_attributes.service.ts +548 -3
  60. package/src/module/linked_attributes/test/linked-attributes.service.spec.ts +244 -0
  61. package/src/module/meta/dto/entity-table.dto.ts +1 -2
  62. package/src/module/meta/service/media-data.service.ts +9 -27
@@ -0,0 +1,244 @@
1
+ import { Test, TestingModule } from '@nestjs/testing';
2
+ import { LinkedAttributesService } from '../service/linked_attributes.service';
3
+ import { DataSource } from 'typeorm';
4
+ import { EntityMasterService } from 'src/module/meta/service/entity-master.service';
5
+ import { AttributeMasterService } from 'src/module/meta/service/attribute-master.service';
6
+ import { SavedFilterService } from 'src/module/filter/service/saved-filter.service';
7
+ import { SavedFilterDetailRepository } from 'src/module/filter/repository/saved.filter-detail.repository';
8
+ import { EntityJSONService } from 'src/module/entity_json/service/entity_json.service';
9
+
10
+ describe('LinkedAttributesService - Phase 1 Tests', () => {
11
+ let service: LinkedAttributesService;
12
+ let dataSource: DataSource;
13
+ let entityMasterService: EntityMasterService;
14
+ let attributeMasterService: AttributeMasterService;
15
+
16
+ const mockDataSource = {
17
+ getRepository: jest.fn(),
18
+ transaction: jest.fn(),
19
+ };
20
+
21
+ const mockEntityMasterService = {
22
+ getEntityData: jest.fn(),
23
+ };
24
+
25
+ const mockAttributeMasterService = {
26
+ findAttributesByMappedEntityType: jest.fn(),
27
+ };
28
+
29
+ const mockSavedFilterService = {
30
+ createEntity: jest.fn(),
31
+ };
32
+
33
+ const mockSavedFilterDetailRepository = {
34
+ findByMappedFilterCode: jest.fn(),
35
+ };
36
+
37
+ const mockEntityJSONService = {
38
+ updateEntityJSON: jest.fn(),
39
+ };
40
+
41
+ const mockLoggedInUser = {
42
+ id: 1,
43
+ organization_id: 100,
44
+ level_type: 'ORG',
45
+ level_id: 100,
46
+ };
47
+
48
+ beforeEach(async () => {
49
+ const module: TestingModule = await Test.createTestingModule({
50
+ providers: [
51
+ LinkedAttributesService,
52
+ { provide: DataSource, useValue: mockDataSource },
53
+ { provide: EntityMasterService, useValue: mockEntityMasterService },
54
+ {
55
+ provide: AttributeMasterService,
56
+ useValue: mockAttributeMasterService,
57
+ },
58
+ { provide: 'SavedFilterService', useValue: mockSavedFilterService },
59
+ {
60
+ provide: SavedFilterDetailRepository,
61
+ useValue: mockSavedFilterDetailRepository,
62
+ },
63
+ { provide: EntityJSONService, useValue: mockEntityJSONService },
64
+ ],
65
+ }).compile();
66
+
67
+ service = module.get<LinkedAttributesService>(LinkedAttributesService);
68
+ dataSource = module.get<DataSource>(DataSource);
69
+ });
70
+
71
+ afterEach(() => {
72
+ jest.clearAllMocks();
73
+ });
74
+
75
+ describe('Task 1.1: generateAttributeKey', () => {
76
+ it('should generate correct attribute key format', () => {
77
+ const result = service.generateAttributeKey('LFMG', 'name', 1);
78
+ expect(result).toBe('LFMG__name__1');
79
+ });
80
+
81
+ it('should handle different sequences', () => {
82
+ expect(service.generateAttributeKey('LFMG', 'name', 1)).toBe(
83
+ 'LFMG__name__1',
84
+ );
85
+ expect(service.generateAttributeKey('LFMG', 'name', 2)).toBe(
86
+ 'LFMG__name__2',
87
+ );
88
+ expect(service.generateAttributeKey('LFMG', 'name', 99)).toBe(
89
+ 'LFMG__name__99',
90
+ );
91
+ });
92
+
93
+ it('should throw error for empty entity_type', () => {
94
+ expect(() => service.generateAttributeKey('', 'name', 1)).toThrow(
95
+ 'applicable_entity_type is required and cannot be empty',
96
+ );
97
+ });
98
+
99
+ it('should throw error for empty attribute_key', () => {
100
+ expect(() => service.generateAttributeKey('LFMG', '', 1)).toThrow(
101
+ 'applicable_attribute_key is required and cannot be empty',
102
+ );
103
+ });
104
+
105
+ it('should throw error for invalid sequence', () => {
106
+ expect(() => service.generateAttributeKey('LFMG', 'name', 0)).toThrow(
107
+ 'sequence must be a positive integer greater than 0',
108
+ );
109
+ expect(() => service.generateAttributeKey('LFMG', 'name', -1)).toThrow(
110
+ 'sequence must be a positive integer greater than 0',
111
+ );
112
+ expect(() => service.generateAttributeKey('LFMG', 'name', 1.5)).toThrow(
113
+ 'sequence must be a positive integer greater than 0',
114
+ );
115
+ });
116
+
117
+ it('should trim whitespace from inputs', () => {
118
+ expect(() =>
119
+ service.generateAttributeKey(' ', 'name', 1),
120
+ ).toThrow();
121
+ expect(() =>
122
+ service.generateAttributeKey('LFMG', ' ', 1),
123
+ ).toThrow();
124
+ });
125
+ });
126
+
127
+ describe('Task 1.2: Validation Engine', () => {
128
+ it('should validate required fields', async () => {
129
+ const payload = {
130
+ field_name: '',
131
+ mapped_entity_type: 'LEAD',
132
+ applicable_entity_type: 'LFMG',
133
+ applicable_attribute_key: 'name',
134
+ organization_id: 100,
135
+ };
136
+
137
+ const result = await service.validateLinkedAttribute(
138
+ payload,
139
+ mockLoggedInUser,
140
+ );
141
+
142
+ expect(result.valid).toBe(false);
143
+ expect(result.errors).toContain(
144
+ "Required field 'field_name' is missing or empty",
145
+ );
146
+ });
147
+
148
+ it('should validate entity type exists', async () => {
149
+ mockEntityMasterService.getEntityData.mockRejectedValue(
150
+ new Error('Not found'),
151
+ );
152
+
153
+ const payload = {
154
+ field_name: 'Father Name',
155
+ mapped_entity_type: 'INVALID',
156
+ applicable_entity_type: 'LFMG',
157
+ applicable_attribute_key: 'name',
158
+ organization_id: 100,
159
+ };
160
+
161
+ const result = await service.validateLinkedAttribute(
162
+ payload,
163
+ mockLoggedInUser,
164
+ );
165
+
166
+ expect(result.valid).toBe(false);
167
+ expect(
168
+ result.errors.some((e) => e.includes('does not exist')),
169
+ ).toBe(true);
170
+ });
171
+
172
+ it('should pass validation for valid payload', async () => {
173
+ // Mock successful validations
174
+ mockEntityMasterService.getEntityData
175
+ .mockResolvedValueOnce({ id: 1 }) // mapped_entity_type
176
+ .mockResolvedValueOnce({ id: 2 }); // applicable_entity_type
177
+
178
+ mockAttributeMasterService.findAttributesByMappedEntityType.mockResolvedValue(
179
+ [{ attribute_key: 'name' }],
180
+ );
181
+
182
+ const mockRepository = {
183
+ createQueryBuilder: jest.fn().mockReturnValue({
184
+ where: jest.fn().mockReturnThis(),
185
+ andWhere: jest.fn().mockReturnThis(),
186
+ getOne: jest.fn().mockResolvedValue(null), // No duplicate
187
+ }),
188
+ };
189
+
190
+ mockDataSource.getRepository.mockReturnValue(mockRepository);
191
+
192
+ const payload = {
193
+ field_name: 'Father Name',
194
+ mapped_entity_type: 'LEAD',
195
+ applicable_entity_type: 'LFMG',
196
+ applicable_attribute_key: 'name',
197
+ organization_id: 100,
198
+ };
199
+
200
+ const result = await service.validateLinkedAttribute(
201
+ payload,
202
+ mockLoggedInUser,
203
+ );
204
+
205
+ expect(result.valid).toBe(true);
206
+ expect(result.errors).toHaveLength(0);
207
+ });
208
+ });
209
+
210
+ describe('Task 1.4: Smart Create Method', () => {
211
+ it('should throw BadRequestException on validation failure', async () => {
212
+ // Mock validation failure
213
+ mockEntityMasterService.getEntityData.mockRejectedValue(
214
+ new Error('Not found'),
215
+ );
216
+
217
+ const dto = {
218
+ field_name: 'Father Name',
219
+ mapped_entity_type: 'INVALID',
220
+ applicable_entity_type: 'LFMG',
221
+ applicable_attribute_key: 'name',
222
+ };
223
+
224
+ await expect(
225
+ service.createLinkedAttributeSmart(dto, mockLoggedInUser),
226
+ ).rejects.toThrow();
227
+ });
228
+ });
229
+
230
+ describe('Integration Tests', () => {
231
+ it('should handle end-to-end attribute key generation', () => {
232
+ // Test the full flow: sequence 1, 2, 3
233
+ expect(service.generateAttributeKey('LFMG', 'name', 1)).toBe(
234
+ 'LFMG__name__1',
235
+ );
236
+ expect(service.generateAttributeKey('LFMG', 'email', 1)).toBe(
237
+ 'LFMG__email__1',
238
+ );
239
+ expect(service.generateAttributeKey('CONTACT', 'phone', 1)).toBe(
240
+ 'CONTACT__phone__1',
241
+ );
242
+ });
243
+ });
244
+ });
@@ -6,6 +6,5 @@ export class EntityTableDto extends EntityTable {
6
6
  operation_list: {};
7
7
  default_filter: {} | null;
8
8
  saved_filter: { label: string; value: number }[] | null;
9
- // shared_filter: { label: string; value: number }[] | null;
10
- shared_filter: any[] | null;
9
+ shared_filter: { label: string; value: number }[] | null;
11
10
  }
@@ -129,17 +129,6 @@ export class MediaDataService extends EntityServiceImpl {
129
129
  jpg: 'image/jpeg',
130
130
  jpeg: 'image/jpeg',
131
131
  png: 'image/png',
132
- gif: 'image/gif',
133
- webp: 'image/webp',
134
- txt: 'text/plain',
135
- html: 'text/html',
136
- htm: 'text/html',
137
- doc: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
138
- docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
139
- xls: 'application/vnd.ms-excel',
140
- xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
141
- ppt: 'application/vnd.ms-powerpoint',
142
- pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
143
132
  };
144
133
  return map[ext] || 'application/octet-stream';
145
134
  }
@@ -182,6 +171,7 @@ export class MediaDataService extends EntityServiceImpl {
182
171
  }
183
172
  }
184
173
 
174
+ // media-data.service.ts
185
175
  async getMediaInlineUrl(id: number, loggedInUser, expiresIn?: number) {
186
176
  try {
187
177
  const entityData = await this.getEntityData(
@@ -191,13 +181,6 @@ export class MediaDataService extends EntityServiceImpl {
191
181
  );
192
182
  const mediaData = entityData as MediaData;
193
183
  let fileSize: number | undefined;
194
-
195
- if (!mediaData) {
196
- throw new Error('Media not found');
197
- }
198
-
199
- const ext = mediaData.file_name.split('.').pop()?.toLowerCase() || '';
200
-
201
184
  if (this.bucketName) {
202
185
  const head = await this.s3
203
186
  .headObject({
@@ -208,23 +191,22 @@ export class MediaDataService extends EntityServiceImpl {
208
191
  fileSize = head.ContentLength;
209
192
  }
210
193
 
194
+ if (!mediaData) {
195
+ throw new Error('Media not found');
196
+ }
197
+
211
198
  const signedUrl = await this.s3.getSignedUrlPromise('getObject', {
212
199
  Bucket: this.bucketName,
213
200
  Key: mediaData.media_url,
214
201
  Expires: Number(expiresIn) || 60 * 5,
215
202
  ResponseContentDisposition: 'inline',
216
- ResponseContentType: this.getContentType(ext),
203
+ ResponseContentType: this.getContentType(
204
+ mediaData.file_name.split('.').pop() || '',
205
+ ),
217
206
  });
218
207
 
219
- let previewUrl = signedUrl;
220
- // if (ext === 'doc' || ext === 'docx') {
221
- // previewUrl =
222
- // `https://view.officeapps.live.com/op/embed.aspx?src=` +
223
- // encodeURIComponent(signedUrl);
224
- // }
225
-
226
208
  return {
227
- signedUrl: previewUrl,
209
+ signedUrl,
228
210
  fileName: mediaData.file_name,
229
211
  id: mediaData.id,
230
212
  size: fileSize,