rez_core 1.0.40 → 1.0.41

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "1.0.40",
3
+ "version": "1.0.41",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -22,19 +22,5 @@ export class MasterController {
22
22
  return this.masterService.processExcel(file);
23
23
  }
24
24
 
25
- @Post('uploadMasterData')
26
- @UseInterceptors(FileInterceptor('file'))
27
- async uploadMasterDataXls(@UploadedFile() file: Express.Multer.File) {
28
- if (!file) {
29
- throw new BadRequestException('File is required');
30
- }
31
- // const tempFilePath = join(__dirname, '../../uploads', `${Date.now()}_${file.originalname}`);
32
- // await writeFile(tempFilePath, file.buffer);
33
-
34
- try {
35
- await this.masterService.uploadMasterData(file.buffer);
36
- } finally {
37
- // FileUtil.deleteFile(tempFilePath);
38
- }
39
- }
25
+
40
26
  }
@@ -1,29 +1,148 @@
1
1
  import { Injectable } from '@nestjs/common';
2
- import { ExcelUtil } from '../../../utils/service/excelUtil.service';
3
2
  import { EntityManager } from 'typeorm';
3
+ import { ExcelUtil } from 'src/utils/service/excelUtil.service';
4
4
  import { EntityMasterService } from '../../meta/service/entity-master.service';
5
5
 
6
+ interface ParentEntity {
7
+ id: number;
8
+ code: string;
9
+ }
10
+
6
11
  @Injectable()
7
12
  export class MasterService {
8
13
  constructor(
9
14
  private readonly entityManager: EntityManager,
10
15
  private readonly entityMasterService: EntityMasterService,
11
- private ExcelUtil: ExcelUtil,
16
+ private readonly excelUtil: ExcelUtil,
12
17
  ) {}
13
18
 
14
- async processExcel(file): Promise<any> {
15
- const data = ExcelUtil.readExcel(file.buffer);
19
+ private readonly metaSheets = [
20
+ 'entity_master',
21
+ 'attribute_master',
22
+ 'list_master',
23
+ 'list_master_items',
24
+ ];
25
+
26
+ private isMetaSheet(sheetName: string): boolean {
27
+ return this.metaSheets.includes(sheetName.toLowerCase());
28
+ }
29
+
30
+ async processExcel(file): Promise<{ message: string }> {
31
+ console.log('📥 Reading Excel file...');
32
+ const data = ExcelUtil.readExcel(file.buffer) as Record<string, Record<string, any>[]>;
33
+
34
+ for (const [sheetName, records] of Object.entries(data)) {
35
+ if (!records.length) continue;
36
+
37
+ const isMeta = this.isMetaSheet(sheetName);
38
+ console.log(`📄 Processing sheet: ${sheetName} | Meta: ${isMeta}`);
39
+
40
+ if (isMeta) {
41
+ await this.upsertData(sheetName, records);
42
+ } else {
43
+ await this.processEntityData(records);
44
+ }
45
+ }
46
+
47
+ return { message: '✅ Data processed successfully' };
48
+ }
49
+
50
+ private async processEntityData(records: Record<string, any>[]): Promise<void> {
51
+ for (const row of records) {
52
+ const entityType = row['entity_type'];
53
+ if (!entityType) {
54
+ console.warn('⚠️ Skipping row without entity_type:', row);
55
+ continue;
56
+ }
57
+
58
+ const { tableName } = await this.getEntityMeta(entityType);
59
+ const attrMap = await this.getAttributeMap(entityType);
60
+ const transformed = this.transformRow(row, attrMap);
61
+
62
+ // Resolve parent_id if parent_type and parent_id are present
63
+ if (row['parent_id'] && row['parent_type']) {
64
+ transformed['parent_id'] = await this.resolveParentId(row['parent_type'], row['parent_id']);
65
+ transformed['parent_type'] = row['parent_type'];
66
+ }
16
67
 
17
- for (const [tableName, records] of Object.entries(data)) {
18
- await this.upsertData(tableName, records);
68
+ await this.insertEntityRow(tableName, transformed);
69
+ }
70
+ }
71
+
72
+ private async getEntityMeta(entityType: string): Promise<{ tableName: string; mappedEntityType: string }> {
73
+ const result = await this.entityManager.query(
74
+ `SELECT db_table_name, mapped_entity_type FROM entity_master WHERE mapped_entity_type = ? LIMIT 1`,
75
+ [entityType],
76
+ );
77
+
78
+ if (!result.length || !result[0].db_table_name) {
79
+ throw new Error(`❌ Entity metadata not found for entity_type: ${entityType}`);
19
80
  }
20
81
 
21
- return { message: 'Data processed successfully' };
82
+ return {
83
+ tableName: result[0].db_table_name,
84
+ mappedEntityType: result[0].mapped_entity_type,
85
+ };
22
86
  }
23
87
 
24
- private async upsertData(tableName: string, records: any[]): Promise<void> {
88
+ private async getAttributeMap(mappedEntityType: string): Promise<Record<string, string>> {
89
+ const attributes = await this.entityManager.query(
90
+ 'SELECT attribute_key FROM attribute_master WHERE mapped_entity_type = ? AND status = "ACTIVE"',
91
+ [mappedEntityType],
92
+ );
93
+
94
+ return attributes.reduce((acc, attr) => {
95
+ acc[attr.attribute_key] = attr.attribute_key;
96
+ return acc;
97
+ }, {} as Record<string, string>);
98
+ }
99
+
100
+ private transformRow(row: Record<string, any>, attrMap: Record<string, string>): Record<string, any> {
101
+ const transformed: Record<string, any> = {};
102
+ for (const key of Object.keys(row)) {
103
+ if (attrMap[key]) {
104
+ transformed[attrMap[key]] = row[key];
105
+ }
106
+ }
107
+ return transformed;
108
+ }
109
+
110
+ private async resolveParentId(parentType: string, parentCode: string): Promise<number> {
111
+ const { tableName } = await this.getEntityMeta(parentType);
112
+ const parent = await this.entityManager.findOne<ParentEntity>(tableName, {
113
+ where: { code: parentCode },
114
+ });
115
+
116
+ if (!parent) {
117
+ throw new Error(`❌ Parent with code "${parentCode}" not found in "${tableName}"`);
118
+ }
119
+
120
+ return parent.id;
121
+ }
122
+
123
+ private async insertEntityRow(tableName: string, data: Record<string, any>): Promise<void> {
124
+ const keys = Object.keys(data);
125
+ if (!keys.length) {
126
+ console.warn('⚠️ Empty data, skipping insert');
127
+ return;
128
+ }
129
+
130
+ await this.entityManager
131
+ .createQueryBuilder()
132
+ .insert()
133
+ .into(tableName)
134
+ .values(data)
135
+ .orUpdate({
136
+ overwrite: keys,
137
+ conflict_target: ['code'],
138
+ })
139
+ .execute();
140
+ }
141
+
142
+ private async upsertData(tableName: string, records: Record<string, any>[]): Promise<void> {
25
143
  if (!records.length) return;
26
144
 
145
+ const keys = Object.keys(records[0]);
27
146
  await this.entityManager.transaction(async (manager) => {
28
147
  for (const record of records) {
29
148
  await manager
@@ -31,27 +150,12 @@ export class MasterService {
31
150
  .insert()
32
151
  .into(tableName)
33
152
  .values(record)
34
- .orUpdate(Object.keys(record), ['id']) // Using 'id' as unique identifier
153
+ .orUpdate({
154
+ overwrite: keys,
155
+ conflict_target: ['id'],
156
+ })
35
157
  .execute();
36
158
  }
37
159
  });
38
160
  }
39
-
40
- async uploadMasterData(file) {
41
- const data = ExcelUtil.readExcel(file.buffer);
42
- await this.importEntityMasterData(data['cr_entity_master']);
43
- }
44
-
45
- private async importEntityMasterData(entityMasterList) {
46
- for (let entityMaster of entityMasterList) {
47
- let existingData = await this.entityMasterService.findByMappedEntityType(entityMaster.mapped_entity_type);
48
-
49
- if (existingData) {
50
- entityMaster.id = existingData.id;
51
- await this.entityMasterService.update(existingData.id, entityMaster);
52
- } else {
53
- await this.entityMasterService.save(entityMaster);
54
- }
55
- }
56
- }
57
161
  }
@@ -34,4 +34,16 @@ export class ModuleAccessController {
34
34
  async updateModuleAccess(@Body() moduleAccessData: any[]) {
35
35
  return this.moduleAccessService.updateModuleAccess(moduleAccessData);
36
36
  }
37
+
38
+ @Post('create-role')
39
+ async createRole(@Body() body: {
40
+ name: string;
41
+ description?: string;
42
+ status?: 'ACTIVE' | 'INACTIVE';
43
+ copyFromRoleId?: number;
44
+ }) {
45
+ return this.moduleAccessService.createRole(body);
46
+ }
47
+
48
+
37
49
  }
@@ -5,6 +5,7 @@ import { Role } from 'src/module/user/entity/role.entity';
5
5
  import { ModuleAccess } from '../entity/module-access.entity';
6
6
  import { ModuleAction } from '../entity/module-action.entity';
7
7
  import { ModuleData } from '../entity/module.entity';
8
+ import { ClockIDGenService } from 'src/utils/service/clockIDGenUtil.service';
8
9
 
9
10
  @Injectable()
10
11
  export class ModuleAccessRepository {
@@ -17,6 +18,8 @@ export class ModuleAccessRepository {
17
18
  private readonly moduleAccessRepo: Repository<ModuleAccess>,
18
19
  @InjectRepository(ModuleAction)
19
20
  private readonly moduleActionRepo: Repository<ModuleAction>,
21
+ private readonly clockIDGenService: ClockIDGenService,
22
+
20
23
  ) {}
21
24
 
22
25
  async getRoles() {
@@ -91,10 +94,10 @@ export class ModuleAccessRepository {
91
94
  // Function to recursively build module hierarchy
92
95
  const buildHierarchy = (parentWbs: string) => {
93
96
  return modules
94
- .filter(
95
- (mod) =>
96
- mod.wbs_code.startsWith(parentWbs) && mod.wbs_code !== parentWbs,
97
- )
97
+ .filter(mod => {
98
+ return mod.wbs_code.startsWith(parentWbs + '.') &&
99
+ mod.wbs_code.split('.').length === parentWbs.split('.').length + 1;
100
+ })
98
101
  .map((mod) => ({
99
102
  name: mod.name,
100
103
  code: mod.module_code,
@@ -150,4 +153,59 @@ export class ModuleAccessRepository {
150
153
  return false;
151
154
  }
152
155
  }
156
+
157
+
158
+ async createRole(body: {
159
+ name: string;
160
+ description?: string;
161
+ status?: 'ACTIVE' | 'INACTIVE';
162
+ copyFromRoleId?: number;
163
+ }) {
164
+ const { name, description, status, copyFromRoleId } = body;
165
+
166
+ const code = this.clockIDGenService.idGenerator('ROL');; // Replace with your custom clock ID generator
167
+
168
+ const newRole = this.roleRepo.create({
169
+ name,
170
+ code,
171
+ description,
172
+ status: status || 'ACTIVE',
173
+ });
174
+
175
+ const savedRole = await this.roleRepo.save(newRole);
176
+
177
+ if (copyFromRoleId) {
178
+ const sourceRole = await this.roleRepo.findOne({ where: { id: copyFromRoleId } });
179
+
180
+ if (!sourceRole) {
181
+ throw new Error('Source role not found');
182
+ }
183
+
184
+ const sourcePermissions = await this.moduleAccessRepo.find({
185
+ where: { role_code: sourceRole.code },
186
+ });
187
+
188
+ const clonedPermissions = sourcePermissions.map((perm) =>
189
+ this.moduleAccessRepo.create({
190
+ role_code: code,
191
+ module_code: perm.module_code,
192
+ action_type: perm.action_type,
193
+ access_flag: perm.access_flag,
194
+ app_code: perm.app_code,
195
+ })
196
+ );
197
+
198
+ await this.moduleAccessRepo.save(clonedPermissions);
199
+ }
200
+
201
+ return {
202
+ success: true,
203
+ msg: 'Role created successfully',
204
+ role: {
205
+ id: savedRole.id,
206
+ name: savedRole.name,
207
+ code: savedRole.code,
208
+ },
209
+ };
210
+ }
153
211
  }
@@ -39,4 +39,14 @@ export class ModuleAccessService {
39
39
  return { success: false, msg: 'Failed to update module access' };
40
40
  }
41
41
  }
42
+
43
+ async createRole(body: {
44
+ name: string;
45
+ description?: string;
46
+ status?: 'ACTIVE' | 'INACTIVE';
47
+ copyFromRoleId?: number;
48
+ }) {
49
+ return this.moduleAccessRepository.createRole(body);
50
+ }
51
+
42
52
  }