rez_core 2.2.143 → 2.2.145
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/dashboard/controller/dashboard.controller.d.ts +1 -0
- package/dist/module/dashboard/controller/dashboard.controller.js +13 -0
- package/dist/module/dashboard/controller/dashboard.controller.js.map +1 -1
- package/dist/module/dashboard/dashboard.module.js +2 -0
- package/dist/module/dashboard/dashboard.module.js.map +1 -1
- package/dist/module/dashboard/repository/dashboard.repository.d.ts +1 -0
- package/dist/module/dashboard/repository/dashboard.repository.js +3 -0
- package/dist/module/dashboard/repository/dashboard.repository.js.map +1 -1
- package/dist/module/dashboard/service/dashboard.service.d.ts +4 -1
- package/dist/module/dashboard/service/dashboard.service.js +20 -2
- package/dist/module/dashboard/service/dashboard.service.js.map +1 -1
- package/dist/module/meta/service/entity-dynamic.service.js +69 -121
- package/dist/module/meta/service/entity-dynamic.service.js.map +1 -1
- package/dist/module/notification/service/email.service.js +1 -1
- package/dist/module/notification/service/email.service.js.map +1 -1
- package/dist/module/user/controller/login.controller.js +1 -1
- package/dist/module/user/controller/login.controller.js.map +1 -1
- package/dist/module/workflow/controller/task.controller.d.ts +2 -0
- package/dist/module/workflow/controller/task.controller.js.map +1 -1
- package/dist/module/workflow/service/task.service.d.ts +7 -0
- package/dist/module/workflow/service/task.service.js +21 -0
- package/dist/module/workflow/service/task.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/dashboard/controller/dashboard.controller.ts +11 -0
- package/src/module/dashboard/dashboard.module.ts +2 -0
- package/src/module/dashboard/repository/dashboard.repository.ts +4 -0
- package/src/module/dashboard/service/dashboard.service.ts +28 -1
- package/src/module/meta/service/entity-dynamic.service.ts +180 -290
- package/src/module/notification/service/email.service.ts +2 -2
- package/src/module/user/controller/login.controller.ts +4 -1
- package/src/module/workflow/controller/task.controller.ts +2 -0
- package/src/module/workflow/service/task.service.ts +40 -0
- package/.vscode/extensions.json +0 -5
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Get,
|
|
4
4
|
Param,
|
|
5
5
|
ParseIntPipe,
|
|
6
|
+
Query,
|
|
6
7
|
Req,
|
|
7
8
|
UseGuards,
|
|
8
9
|
} from '@nestjs/common';
|
|
@@ -22,4 +23,14 @@ export class DashboardController {
|
|
|
22
23
|
const loggedInUser = req.user.userData;
|
|
23
24
|
return this.dashboardService.getDashboardPage(pageId, loggedInUser);
|
|
24
25
|
}
|
|
26
|
+
|
|
27
|
+
@Get('pages')
|
|
28
|
+
@UseGuards(JwtAuthGuard)
|
|
29
|
+
async getPages(
|
|
30
|
+
@Query('mapped_entity_type') mapped_entity_type: string,
|
|
31
|
+
@Req() req: any,
|
|
32
|
+
) {
|
|
33
|
+
const loggedInUser = req.user.userData;
|
|
34
|
+
return this.dashboardService.getPages(mapped_entity_type, loggedInUser);
|
|
35
|
+
}
|
|
25
36
|
}
|
|
@@ -6,11 +6,13 @@ import { DashboardPageData } from './entity/dashboard_page_data.entity';
|
|
|
6
6
|
import { DashboardController } from './controller/dashboard.controller';
|
|
7
7
|
import { DashboardService } from './service/dashboard.service';
|
|
8
8
|
import { DashboardRepository } from './repository/dashboard.repository';
|
|
9
|
+
import { ModuleModule } from '../module/module.module';
|
|
9
10
|
|
|
10
11
|
@Module({
|
|
11
12
|
imports: [
|
|
12
13
|
EntityModule,
|
|
13
14
|
TypeOrmModule.forFeature([WidgetMaster, DashboardPageData]),
|
|
15
|
+
ModuleModule
|
|
14
16
|
],
|
|
15
17
|
controllers: [DashboardController],
|
|
16
18
|
providers: [DashboardService, DashboardRepository],
|
|
@@ -7,6 +7,10 @@ import { WidgetMaster } from '../entity/widget_master.entity';
|
|
|
7
7
|
export class DashboardRepository {
|
|
8
8
|
constructor(private readonly dataSource: DataSource) {}
|
|
9
9
|
|
|
10
|
+
async getPages(mapped_entity_type:string, loggedInUser:any){
|
|
11
|
+
return await this.dataSource.query(`SELECT * FROM cr_dashboard_page_data WHERE mapped_entity_type='${ mapped_entity_type}' AND applicable_type='${loggedInUser.level_type}' AND applicable_id='${loggedInUser.level_id}' AND organization_id='${loggedInUser.organization_id}' `);
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
async getDashboardPageData(
|
|
11
15
|
pageId: number,
|
|
12
16
|
organization_id: number,
|
|
@@ -1,10 +1,37 @@
|
|
|
1
1
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
2
2
|
import { DashboardRepository } from '../repository/dashboard.repository';
|
|
3
|
+
import { ModuleAccessService } from 'src/module/module/service/module-access.service';
|
|
3
4
|
|
|
4
5
|
@Injectable()
|
|
5
6
|
export class DashboardService {
|
|
6
|
-
constructor(private readonly dashboardRepo: DashboardRepository
|
|
7
|
+
constructor(private readonly dashboardRepo: DashboardRepository,
|
|
8
|
+
private readonly moduleAccessService: ModuleAccessService
|
|
9
|
+
) {}
|
|
7
10
|
|
|
11
|
+
async getPages(mapped_entity_type: string, loggedInUser: any) {
|
|
12
|
+
const pages = await this.dashboardRepo.getPages(mapped_entity_type, loggedInUser);
|
|
13
|
+
|
|
14
|
+
const access = await this.moduleAccessService.getUserPermissions({
|
|
15
|
+
userId: loggedInUser.id,
|
|
16
|
+
appcode: loggedInUser.appcode,
|
|
17
|
+
level_type: loggedInUser.level_type,
|
|
18
|
+
level_id: loggedInUser.level_id,
|
|
19
|
+
organization_id: loggedInUser.organization_id,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Build a set of accessible codes
|
|
23
|
+
const allowedCodes = new Set(
|
|
24
|
+
access
|
|
25
|
+
.filter(a => a.action === 'VIEW' && a.access === 1)
|
|
26
|
+
.map(a => a.code)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Filter pages based on access
|
|
30
|
+
const filteredPages = pages.filter(page => allowedCodes.has(page.code));
|
|
31
|
+
|
|
32
|
+
return filteredPages ;
|
|
33
|
+
}
|
|
34
|
+
|
|
8
35
|
async getDashboardPage(pageId: number, loggedInUser: any) {
|
|
9
36
|
const organizationId = loggedInUser.organization_id;
|
|
10
37
|
// 1. Get page data
|
|
@@ -17,6 +17,7 @@ export class EntityDynamicService {
|
|
|
17
17
|
entityData: Record<string, any>,
|
|
18
18
|
loggedInUser: any,
|
|
19
19
|
): Promise<any> {
|
|
20
|
+
|
|
20
21
|
const organizationId = loggedInUser.organization_id;
|
|
21
22
|
|
|
22
23
|
const tableName = await this.getTableName(entityType, organizationId);
|
|
@@ -41,6 +42,7 @@ export class EntityDynamicService {
|
|
|
41
42
|
entityData.level_type = loggedInUser.level_type;
|
|
42
43
|
if (!entityData.level_id) entityData.level_id = loggedInUser.level_id;
|
|
43
44
|
if (!entityData.status) entityData.status = statusList[0].id;
|
|
45
|
+
if( !entityData.entity_type ) entityData.entity_type = entityType;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
if (!entityData.code && loggedInUser) {
|
|
@@ -90,133 +92,77 @@ export class EntityDynamicService {
|
|
|
90
92
|
|
|
91
93
|
// ----------------------------- get entity with relations
|
|
92
94
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
// ----------------------------- create entity with relations
|
|
96
|
+
async createEntityWithRelation(
|
|
97
|
+
entityType: string,
|
|
98
|
+
data: Record<string, any>,
|
|
99
|
+
loggedInUser: any,
|
|
100
|
+
): Promise<any> {
|
|
101
|
+
const organizationId = loggedInUser.organization_id;
|
|
102
|
+
|
|
103
|
+
const getRelation = await this.dataSource.query(
|
|
104
|
+
`SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
|
|
105
|
+
[organizationId, entityType],
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const { mappedEntities, ...mainData } = data;
|
|
109
|
+
|
|
110
|
+
// create main entity
|
|
111
|
+
const createdEntityData = await this.createEntity(
|
|
112
|
+
entityType,
|
|
113
|
+
mainData,
|
|
114
|
+
loggedInUser,
|
|
115
|
+
);
|
|
116
|
+
const mainID = createdEntityData.insertId || createdEntityData.id;
|
|
117
|
+
|
|
118
|
+
if (mappedEntities && getRelation.length > 0) {
|
|
119
|
+
for (const relation of getRelation) {
|
|
120
|
+
const targetEntityType = relation.target_entity_type;
|
|
121
|
+
const relationType = relation.relation_type;
|
|
122
|
+
const relationId = relation.relation_id;
|
|
99
123
|
|
|
100
|
-
|
|
101
|
-
`SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
|
|
102
|
-
[organizationId, entityType],
|
|
103
|
-
);
|
|
124
|
+
if (!mappedEntities[targetEntityType]) continue;
|
|
104
125
|
|
|
105
|
-
|
|
126
|
+
// normalize: always array
|
|
127
|
+
const entityDataArray = Array.isArray(mappedEntities[targetEntityType])
|
|
128
|
+
? mappedEntities[targetEntityType]
|
|
129
|
+
: [mappedEntities[targetEntityType]];
|
|
106
130
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const relationTypeResult = await this.dataSource.query(
|
|
130
|
-
`SELECT * FROM cr_list_master_items WHERE organization_id = ? AND id = ?`,
|
|
131
|
-
[organizationId, relationId],
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
relationTypeResult[0]?.value == 'ONE_TO_MANY' ||
|
|
136
|
-
relationTypeResult[0]?.value == 'MANY_TO_ONE'
|
|
137
|
-
) {
|
|
138
|
-
// Expect array of objects
|
|
139
|
-
if (Array.isArray(entityData)) {
|
|
140
|
-
for (const item of entityData) {
|
|
141
|
-
// Add foreign key reference to main entity
|
|
142
|
-
const itemWithRef = {
|
|
143
|
-
...item,
|
|
144
|
-
entity_type: targetEntityType,
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const createdRelatedEntity = await this.createEntity(
|
|
148
|
-
targetEntityType,
|
|
149
|
-
itemWithRef,
|
|
150
|
-
loggedInUser,
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
// SAVE ENTRY IN cr_entity_relation_data
|
|
154
|
-
|
|
155
|
-
await this.dataSource.query(
|
|
156
|
-
`INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
|
|
157
|
-
[
|
|
158
|
-
mainID,
|
|
159
|
-
entityType,
|
|
160
|
-
createdRelatedEntity.insertId,
|
|
161
|
-
targetEntityType,
|
|
162
|
-
relationType,
|
|
163
|
-
],
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
} else {
|
|
167
|
-
throw new Error(
|
|
168
|
-
`Expected array for ONE_TO_MANY relationship with ${targetEntityType}`,
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
} else if (
|
|
172
|
-
relationTypeResult[0]?.value == 'ONE_TO_ONE' ||
|
|
173
|
-
relationTypeResult[0]?.value == 'MANY_TO_ONE'
|
|
174
|
-
) {
|
|
175
|
-
// Expect single object
|
|
176
|
-
if (!Array.isArray(entityData)) {
|
|
177
|
-
// Add foreign key reference to main entity
|
|
178
|
-
const entityWithRef = {
|
|
179
|
-
...entityData,
|
|
180
|
-
entity_type: targetEntityType,
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
const createdRelatedEntity = await this.createEntity(
|
|
184
|
-
targetEntityType,
|
|
185
|
-
entityWithRef,
|
|
186
|
-
loggedInUser,
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
// SAVE ENTRY IN cr_entity_relation_data
|
|
190
|
-
await this.dataSource.query(
|
|
191
|
-
`INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
|
|
192
|
-
[
|
|
193
|
-
mainID,
|
|
194
|
-
entityType,
|
|
195
|
-
createdRelatedEntity.insertId,
|
|
196
|
-
targetEntityType,
|
|
197
|
-
relationType,
|
|
198
|
-
],
|
|
199
|
-
);
|
|
200
|
-
} else {
|
|
201
|
-
throw new Error(
|
|
202
|
-
`Expected single object for ONE_TO_ONE relationship with ${targetEntityType}`,
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
131
|
+
for (const item of entityDataArray) {
|
|
132
|
+
const itemWithRef = {
|
|
133
|
+
...item,
|
|
134
|
+
entity_type: targetEntityType,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const createdRelatedEntity = await this.createEntity(
|
|
138
|
+
targetEntityType,
|
|
139
|
+
itemWithRef,
|
|
140
|
+
loggedInUser,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
await this.dataSource.query(
|
|
144
|
+
`INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
|
|
145
|
+
[
|
|
146
|
+
mainID,
|
|
147
|
+
entityType,
|
|
148
|
+
createdRelatedEntity.insertId,
|
|
149
|
+
targetEntityType,
|
|
150
|
+
relationType,
|
|
151
|
+
],
|
|
152
|
+
);
|
|
207
153
|
}
|
|
208
154
|
}
|
|
209
|
-
|
|
210
|
-
return {
|
|
211
|
-
mainEntity: {
|
|
212
|
-
id: mainID,
|
|
213
|
-
entityType: entityType,
|
|
214
|
-
data: createdEntityData,
|
|
215
|
-
},
|
|
216
|
-
relatedEntities: relationResults,
|
|
217
|
-
};
|
|
218
155
|
}
|
|
219
156
|
|
|
157
|
+
return {
|
|
158
|
+
mainEntity: {
|
|
159
|
+
id: mainID,
|
|
160
|
+
entityType,
|
|
161
|
+
data: createdEntityData,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
220
166
|
// ----------------------------- get entity with relations
|
|
221
167
|
async getEntityWithRelation(
|
|
222
168
|
entityType: string,
|
|
@@ -247,204 +193,133 @@ export class EntityDynamicService {
|
|
|
247
193
|
return response;
|
|
248
194
|
}
|
|
249
195
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
196
|
+
// ----------------------------- formatMappedEntities
|
|
197
|
+
async formatMappedEntities(
|
|
198
|
+
relatedEntities: any[],
|
|
199
|
+
loggedInUser: any,
|
|
200
|
+
): Promise<any> {
|
|
201
|
+
const mappedEntities: any = {};
|
|
255
202
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const relationType = relation.relation_type;
|
|
203
|
+
for (const relation of relatedEntities) {
|
|
204
|
+
const targetEntityType = relation.target_entity_type;
|
|
205
|
+
const targetEntityId = relation.target_entity_id;
|
|
260
206
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
if (!mappedEntities[targetEntityType]) {
|
|
269
|
-
// Initialize based on relation type
|
|
270
|
-
if (relationType === 'ONE_TO_MANY') {
|
|
271
|
-
mappedEntities[targetEntityType] = [];
|
|
272
|
-
} else if (
|
|
273
|
-
relationType === 'ONE_TO_ONE' ||
|
|
274
|
-
relationType === 'MANY_TO_ONE'
|
|
275
|
-
) {
|
|
276
|
-
mappedEntities[targetEntityType] = null;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
207
|
+
const entityData = await this.getEntity(
|
|
208
|
+
targetEntityType,
|
|
209
|
+
targetEntityId,
|
|
210
|
+
loggedInUser,
|
|
211
|
+
);
|
|
279
212
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
} else if (
|
|
283
|
-
relationType === 'ONE_TO_ONE' ||
|
|
284
|
-
relationType === 'MANY_TO_ONE'
|
|
285
|
-
) {
|
|
286
|
-
mappedEntities[targetEntityType] = entityData;
|
|
287
|
-
}
|
|
213
|
+
if (!mappedEntities[targetEntityType]) {
|
|
214
|
+
mappedEntities[targetEntityType] = [];
|
|
288
215
|
}
|
|
289
216
|
|
|
290
|
-
|
|
217
|
+
mappedEntities[targetEntityType].push(entityData);
|
|
291
218
|
}
|
|
292
219
|
|
|
220
|
+
return mappedEntities;
|
|
221
|
+
}
|
|
222
|
+
|
|
293
223
|
// ----------------------------- update with relations
|
|
294
224
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
225
|
+
// ----------------------------- update entity with relations
|
|
226
|
+
async updateEntityWithRelations(
|
|
227
|
+
entityType: string,
|
|
228
|
+
id: number | string,
|
|
229
|
+
data: Record<string, any>,
|
|
230
|
+
loggedInUser: any,
|
|
231
|
+
): Promise<any> {
|
|
232
|
+
const organizationId = loggedInUser.organization_id;
|
|
233
|
+
const { mappedEntities, ...mainData } = data;
|
|
302
234
|
|
|
303
|
-
|
|
235
|
+
// Update main entity
|
|
236
|
+
const updatedMainEntity = await this.updateEntity(entityType, id, mainData, loggedInUser);
|
|
304
237
|
|
|
305
|
-
|
|
306
|
-
|
|
238
|
+
const updatedRelations: Record<string, any> = {};
|
|
239
|
+
|
|
240
|
+
if (mappedEntities) {
|
|
241
|
+
const getRelationDefs = await this.dataSource.query(
|
|
242
|
+
`SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
|
|
243
|
+
[organizationId, entityType],
|
|
244
|
+
);
|
|
307
245
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const existingRelations = await this.dataSource.query(
|
|
312
|
-
`SELECT * FROM cr_entity_relation_data WHERE source_entity_type = ? AND source_entity_id = ?`,
|
|
313
|
-
[entityType, id],
|
|
246
|
+
for (const [targetEntityType, rawEntityData] of Object.entries(mappedEntities)) {
|
|
247
|
+
const relationDef = getRelationDefs.find(
|
|
248
|
+
(r) => r.target_entity_type === targetEntityType,
|
|
314
249
|
);
|
|
250
|
+
if (!relationDef) continue;
|
|
251
|
+
|
|
252
|
+
const relationType = relationDef.relation_type;
|
|
253
|
+
const entityArray = Array.isArray(rawEntityData) ? rawEntityData : [rawEntityData];
|
|
315
254
|
|
|
316
|
-
//
|
|
317
|
-
const
|
|
318
|
-
`SELECT * FROM
|
|
319
|
-
[
|
|
255
|
+
// Delete previous relations and related entities
|
|
256
|
+
const existingRelationsForType = await this.dataSource.query(
|
|
257
|
+
`SELECT * FROM cr_entity_relation_data WHERE source_entity_type = ? AND source_entity_id = ? AND target_entity_type = ?`,
|
|
258
|
+
[entityType, id, targetEntityType],
|
|
320
259
|
);
|
|
321
260
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
261
|
+
for (const existingRel of existingRelationsForType) {
|
|
262
|
+
// Delete the related entity
|
|
263
|
+
await this.deleteEntity(existingRel.target_entity_type, existingRel.target_entity_id, loggedInUser);
|
|
264
|
+
|
|
265
|
+
// Delete the relation row
|
|
266
|
+
await this.dataSource.query(
|
|
267
|
+
`DELETE FROM cr_entity_relation_data WHERE id = ?`,
|
|
268
|
+
[existingRel.id],
|
|
328
269
|
);
|
|
270
|
+
}
|
|
329
271
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
272
|
+
// Create/update new entities & relations
|
|
273
|
+
const updatedEntities: any[] = [];
|
|
274
|
+
|
|
275
|
+
for (const item of entityArray) {
|
|
276
|
+
let targetEntityId;
|
|
277
|
+
let entityData;
|
|
278
|
+
|
|
279
|
+
if (item.id) {
|
|
280
|
+
// Update existing entity
|
|
281
|
+
await this.updateEntity(targetEntityType, item.id, item, loggedInUser);
|
|
282
|
+
targetEntityId = item.id;
|
|
283
|
+
entityData = await this.getEntity(targetEntityType, targetEntityId, loggedInUser);
|
|
284
|
+
} else {
|
|
285
|
+
// Create new entity
|
|
286
|
+
const createdEntity = await this.createEntity(targetEntityType, item, loggedInUser);
|
|
287
|
+
targetEntityId = createdEntity.insertId || createdEntity.id;
|
|
288
|
+
entityData = await this.getEntity(targetEntityType, targetEntityId, loggedInUser);
|
|
335
289
|
}
|
|
336
290
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
291
|
+
// Insert relation
|
|
292
|
+
await this.dataSource.query(
|
|
293
|
+
`INSERT INTO cr_entity_relation_data
|
|
294
|
+
(source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type)
|
|
295
|
+
VALUES (?, ?, ?, ?, ?)`,
|
|
296
|
+
[id, entityType, targetEntityId, targetEntityType, relationType],
|
|
340
297
|
);
|
|
341
298
|
|
|
342
299
|
if (relationType === 'ONE_TO_MANY') {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
for (const existingRel of existingRelationsForType) {
|
|
348
|
-
await this.dataSource.query(
|
|
349
|
-
`DELETE FROM cr_entity_relation_data WHERE id = ?`,
|
|
350
|
-
[existingRel.id],
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Create new relations
|
|
355
|
-
for (const item of entityData) {
|
|
356
|
-
let targetEntityId;
|
|
357
|
-
|
|
358
|
-
if (item.id) {
|
|
359
|
-
// Update existing entity
|
|
360
|
-
await this.updateEntity(
|
|
361
|
-
targetEntityType,
|
|
362
|
-
item.id,
|
|
363
|
-
item,
|
|
364
|
-
loggedInUser,
|
|
365
|
-
);
|
|
366
|
-
targetEntityId = item.id;
|
|
367
|
-
} else {
|
|
368
|
-
// Create new entity
|
|
369
|
-
const createdEntity = await this.createEntity(
|
|
370
|
-
targetEntityType,
|
|
371
|
-
item,
|
|
372
|
-
loggedInUser,
|
|
373
|
-
);
|
|
374
|
-
targetEntityId = createdEntity.insertId || createdEntity.id;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Create relation entry
|
|
378
|
-
await this.dataSource.query(
|
|
379
|
-
`INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
|
|
380
|
-
[
|
|
381
|
-
id,
|
|
382
|
-
entityType,
|
|
383
|
-
targetEntityId,
|
|
384
|
-
targetEntityType,
|
|
385
|
-
relationType,
|
|
386
|
-
],
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
} else {
|
|
390
|
-
throw new Error(
|
|
391
|
-
`Expected array for ONE_TO_MANY relationship with ${targetEntityType}`,
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
} else if (
|
|
395
|
-
relationType === 'ONE_TO_ONE' ||
|
|
396
|
-
relationType === 'MANY_TO_ONE'
|
|
397
|
-
) {
|
|
398
|
-
// Handle single entity
|
|
399
|
-
if (!Array.isArray(entityData)) {
|
|
400
|
-
const singleEntityData = entityData as Record<string, any>;
|
|
401
|
-
let targetEntityId;
|
|
402
|
-
|
|
403
|
-
if (singleEntityData.id) {
|
|
404
|
-
// Update existing entity
|
|
405
|
-
await this.updateEntity(
|
|
406
|
-
targetEntityType,
|
|
407
|
-
singleEntityData.id,
|
|
408
|
-
singleEntityData,
|
|
409
|
-
loggedInUser,
|
|
410
|
-
);
|
|
411
|
-
targetEntityId = singleEntityData.id;
|
|
412
|
-
} else {
|
|
413
|
-
// Create new entity
|
|
414
|
-
const createdEntity = await this.createEntity(
|
|
415
|
-
targetEntityType,
|
|
416
|
-
singleEntityData,
|
|
417
|
-
loggedInUser,
|
|
418
|
-
);
|
|
419
|
-
targetEntityId = createdEntity.insertId || createdEntity.id;
|
|
420
|
-
|
|
421
|
-
// Create relation entry if it doesn't exist
|
|
422
|
-
const existingRel = existingRelationsForType[0];
|
|
423
|
-
if (!existingRel) {
|
|
424
|
-
await this.dataSource.query(
|
|
425
|
-
`INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
|
|
426
|
-
[
|
|
427
|
-
id,
|
|
428
|
-
entityType,
|
|
429
|
-
targetEntityId,
|
|
430
|
-
targetEntityType,
|
|
431
|
-
relationType,
|
|
432
|
-
],
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
} else {
|
|
437
|
-
throw new Error(
|
|
438
|
-
`Expected single object for ONE_TO_ONE relationship with ${targetEntityType}`,
|
|
439
|
-
);
|
|
440
|
-
}
|
|
300
|
+
updatedEntities.push(entityData);
|
|
301
|
+
} else if (relationType === 'ONE_TO_ONE' || relationType === 'MANY_TO_ONE') {
|
|
302
|
+
updatedEntities[0] = entityData; // single object
|
|
441
303
|
}
|
|
442
304
|
}
|
|
443
|
-
}
|
|
444
305
|
|
|
445
|
-
|
|
306
|
+
// Assign to response mappedEntities
|
|
307
|
+
updatedRelations[targetEntityType] =
|
|
308
|
+
relationType === 'ONE_TO_MANY' ? updatedEntities : updatedEntities[0];
|
|
309
|
+
}
|
|
446
310
|
}
|
|
447
311
|
|
|
312
|
+
return {
|
|
313
|
+
mainEntity: {
|
|
314
|
+
id,
|
|
315
|
+
entityType,
|
|
316
|
+
data: updatedMainEntity,
|
|
317
|
+
},
|
|
318
|
+
relatedEntities: updatedRelations,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
|
|
448
323
|
// -----------------------------
|
|
449
324
|
async updateEntity(
|
|
450
325
|
entityType: string,
|
|
@@ -472,6 +347,21 @@ export class EntityDynamicService {
|
|
|
472
347
|
entityData.enterprise_id = loggedInUser.enterprise_id;
|
|
473
348
|
}
|
|
474
349
|
|
|
350
|
+
if (!entityData.code && loggedInUser) {
|
|
351
|
+
const result = await this.dataSource.query(
|
|
352
|
+
`SELECT MAX(CAST(SUBSTRING(code, LENGTH(entity_type) + 1) AS UNSIGNED)) AS max_seq_no
|
|
353
|
+
FROM ${tableName}
|
|
354
|
+
WHERE entity_type = ?`,
|
|
355
|
+
[entityData.entity_type],
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
// result will be like [ { max_seq_no: 12 } ]
|
|
359
|
+
let maxSeqNo = result?.[0]?.max_seq_no ? Number(result[0].max_seq_no) : 0;
|
|
360
|
+
|
|
361
|
+
maxSeqNo += 1;
|
|
362
|
+
entityData.code = `${entityData.entity_type}${maxSeqNo}`;
|
|
363
|
+
}
|
|
364
|
+
|
|
475
365
|
const bypassColumn = [
|
|
476
366
|
'created_date',
|
|
477
367
|
'created_by',
|
|
@@ -63,7 +63,10 @@ export class LoginController {
|
|
|
63
63
|
// Call LoginService to validate user, create session, and return JWT
|
|
64
64
|
const data = await this.loginService.loginWithGoogle(email, name);
|
|
65
65
|
|
|
66
|
-
if (!('accessToken' in data) || !data.accessToken)
|
|
66
|
+
if (!('accessToken' in data) || !data.accessToken)
|
|
67
|
+
return res.redirect(
|
|
68
|
+
`${this.configService.get('BASE_URL')}/auth?email=${email}&error='User not found'`,
|
|
69
|
+
);
|
|
67
70
|
|
|
68
71
|
const { accessToken, appcode } = data;
|
|
69
72
|
return res.redirect(
|