@simitgroup/simpleapp-generator 1.0.58 → 1.0.60

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 (101) hide show
  1. package/README.md +3 -2
  2. package/dist/buildinschemas/branch.d.ts.map +1 -1
  3. package/dist/buildinschemas/branch.js +1 -0
  4. package/dist/buildinschemas/branch.js.map +1 -1
  5. package/dist/buildinschemas/organization.d.ts.map +1 -1
  6. package/dist/buildinschemas/organization.js +1 -0
  7. package/dist/buildinschemas/organization.js.map +1 -1
  8. package/dist/buildinschemas/permission.js +5 -5
  9. package/dist/buildinschemas/permission.js.map +1 -1
  10. package/dist/buildinschemas/user.d.ts.map +1 -1
  11. package/dist/buildinschemas/user.js +4 -1
  12. package/dist/buildinschemas/user.js.map +1 -1
  13. package/dist/framework.js +1 -1
  14. package/dist/framework.js.map +1 -1
  15. package/dist/generate.js +6 -1
  16. package/dist/generate.js.map +1 -1
  17. package/dist/type.d.ts +1 -0
  18. package/dist/type.d.ts.map +1 -1
  19. package/docs/backend.md +89 -0
  20. package/docs/formula.md +0 -0
  21. package/docs/frontend.md +57 -0
  22. package/docs/jsonschema.md +12 -3
  23. package/package.json +1 -1
  24. package/src/buildinschemas/branch.ts +1 -0
  25. package/src/buildinschemas/organization.ts +1 -0
  26. package/src/buildinschemas/permission.ts +5 -5
  27. package/src/buildinschemas/user.ts +4 -1
  28. package/src/framework.ts +1 -1
  29. package/src/generate.ts +6 -1
  30. package/src/type.ts +1 -0
  31. package/templates/basic/nest/controller.ts.eta +5 -3
  32. package/templates/basic/nest/model.ts.eta +32 -7
  33. package/templates/basic/nuxt/pages.crud.vue.eta +59 -163
  34. package/templates/basic/nuxt/pages.index.vue.eta +225 -0
  35. package/templates/nest/.env._eta +1 -0
  36. package/templates/nest/src/simpleapp/generate/commons/exceptions/SimpleAppExceptionFilter.ts.eta +1 -1
  37. package/templates/nest/src/simpleapp/generate/commons/roles/roles.group.ts.eta +1 -1
  38. package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +157 -23
  39. package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +22 -15
  40. package/templates/nest/src/simpleapp/generate/types/index.ts.eta +8 -0
  41. package/templates/nest/src/simpleapp/profile/profile.controller.ts.eta +25 -2
  42. package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +23 -6
  43. package/templates/nest/src/simpleapp/services/branch.service.ts.eta +41 -40
  44. package/templates/nest/src/simpleapp/services/user.service.ts.eta +10 -9
  45. package/templates/nuxt/app.vue.eta +2 -1
  46. package/templates/nuxt/assets/css/style.css._eta +3 -12
  47. package/templates/nuxt/assets/primevue/passthrough.ts._eta +24 -20
  48. package/templates/nuxt/components/ButtonCreateTenant.vue.eta +30 -23
  49. package/templates/nuxt/components/ButtonHome.vue.eta +15 -2
  50. package/templates/nuxt/components/ButtonMenuPicker.vue.eta +5 -20
  51. package/templates/nuxt/components/ButtonPermissionInfo.vue.eta +5 -7
  52. package/templates/nuxt/components/ButtonProfile.vue.eta +42 -25
  53. package/templates/nuxt/components/CrudSimple.vue.eta +1 -1
  54. package/templates/nuxt/components/EventDecision.vue.eta +115 -0
  55. package/templates/nuxt/components/EventNotification.vue.eta +157 -0
  56. package/templates/nuxt/components/HeaderBar.vue.eta +2 -2
  57. package/templates/nuxt/components/Invitation.vue.eta +3 -3
  58. package/templates/nuxt/components/SelectBranch.vue.eta +5 -2
  59. package/templates/nuxt/components/SimpleAppDatatable.vue.eta +151 -5
  60. package/templates/nuxt/components/TenantPicker.vue.eta +75 -0
  61. package/templates/nuxt/components/UserProfileListItem.vue.eta +65 -0
  62. package/templates/nuxt/components/renderers/BooleanRender.vue.eta +7 -0
  63. package/templates/nuxt/components/renderers/DateRender.vue.eta +6 -0
  64. package/templates/nuxt/components/renderers/ForeignKeyRender.vue.eta +10 -0
  65. package/templates/nuxt/components/renderers/MoneyRender.vue.eta +7 -0
  66. package/templates/nuxt/components/renderers/MultiTextRender.vue.eta +11 -0
  67. package/templates/nuxt/composables/getDocument.generate.ts.eta +4 -0
  68. package/templates/nuxt/composables/getMenus.generate.ts.eta +35 -31
  69. package/templates/nuxt/composables/getUserStore.generate.ts.eta +6 -1
  70. package/templates/nuxt/composables/goTo.generate.ts.eta +15 -0
  71. package/templates/nuxt/composables/notifications.generate.ts.eta +21 -0
  72. package/templates/nuxt/composables/stringHelper.generate.ts.eta +11 -1
  73. package/templates/nuxt/error.vue._eta +20 -5
  74. package/templates/nuxt/layouts/documentlist.vue.eta +166 -0
  75. package/templates/nuxt/middleware/30.acl.global.ts.eta +4 -1
  76. package/templates/nuxt/pages/[xorg]/organization/index.vue.eta +4 -4
  77. package/templates/nuxt/pages/[xorg]/profile.vue.eta +6 -0
  78. package/templates/nuxt/pages/[xorg]/user/[id].vue.eta +6 -0
  79. package/templates/nuxt/pages/[xorg]/user/index.vue.eta +211 -377
  80. package/templates/nuxt/pages/[xorg]/user.vue.eta +197 -0
  81. package/templates/nuxt/pages/index.vue._eta +101 -0
  82. package/templates/nuxt/pages/profile.vue.eta +94 -0
  83. package/templates/nuxt/plugins/10.simpleapp-event.ts.eta +4 -4
  84. package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +11 -10
  85. package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +69 -17
  86. package/templates/nuxt/simpleapp/generate/commons/documents.ts.eta +6 -3
  87. package/templates/nuxt/tailwind.config.ts._eta +10 -0
  88. package/templates/nuxt/types/documentlist.ts.eta +9 -0
  89. package/templates/nuxt/types/events.ts.eta +20 -0
  90. package/templates/nuxt/types/index.ts.eta +6 -79
  91. package/templates/nuxt/types/notifications.ts.eta +16 -0
  92. package/templates/nuxt/types/others.ts.eta +42 -0
  93. package/templates/nuxt/types/user.ts.eta +44 -0
  94. package/tsconfig.tsbuildinfo +1 -1
  95. package/templates/nest/src/simpleapp/generate/models/perm.model.ts.eta +0 -52
  96. package/templates/nest/src/simpleapp/generate/models/tenant.model.ts.eta +0 -43
  97. package/templates/nest/src/simpleapp/generate/models/user.model.ts.eta +0 -56
  98. package/templates/nuxt/components/EventMonitor.vue.eta +0 -85
  99. package/templates/nuxt/pages/[xorg]/tenant/index.vue.eta +0 -89
  100. package/templates/nuxt/pages/index.vue.eta +0 -116
  101. package/templates/nuxt/simpleapp/generate/commons/events.ts.eta +0 -11
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { Injectable, Scope,Inject,Logger, BadRequestException } from '@nestjs/common';
8
8
  import { Model, model, connect, PipelineStage } from 'mongoose';
9
+ import {ModifiedCollection,ModifiedRecords} from '../types'
9
10
  import _ from 'lodash'
10
11
  import { Module } from '@nestjs/common';
11
12
  import * as jwt from 'jsonwebtoken';
@@ -20,8 +21,10 @@ import { Permission, } from './../types/perm.type';
20
21
  import {ProfileUserBranch , ProfileUserInvites} from '../../profile/profile.types'
21
22
 
22
23
  import {ClientSession} from 'mongoose'
23
- @Injectable()
24
+
25
+ @Injectable({scope:Scope.REQUEST})
24
26
  export class UserContext {
27
+ protected sessionId : string =crypto.randomUUID()
25
28
  protected logger = new Logger()
26
29
  protected uid: string = '';
27
30
  protected _id: string = '';
@@ -41,19 +44,20 @@ export class UserContext {
41
44
  protected orgCode: string = '';
42
45
  protected orgName: string = '';
43
46
  protected branches: any[] = []
47
+ protected lastActivity : string = new Date().toISOString()
44
48
  protected invites: any[] = [] //User + field tenant:Tenant[]
45
49
  protected roles: string[] = [];
46
-
50
+ protected modifiedRecords:ModifiedRecords = {createds:{},updateds:{},deleteds:{}}
47
51
 
48
52
  constructor(
49
53
  private readonly usermodel:Model<User>,
50
54
  private readonly permmodel:Model<Permission>,
51
- private dbsession:ClientSession
55
+ private dbsession:ClientSession,
56
+
52
57
  ) {
53
58
 
54
59
  }
55
60
  getDBSession = ():ClientSession => this.dbsession
56
-
57
61
  getId = () => this._id;
58
62
  getUid = () => this.uid;
59
63
  getUname = () => this.uname;
@@ -64,6 +68,7 @@ export class UserContext {
64
68
  getEmail = () => this.email;
65
69
  getGroup = () => this.group;
66
70
  getRoles = () => this.roles;
71
+ getModifieds = () => this.modifiedRecords
67
72
  getBranches = ():ProfileUserBranch[] => {
68
73
  this.branches;
69
74
  const data:ProfileUserBranch[] = []
@@ -118,21 +123,19 @@ export class UserContext {
118
123
  */
119
124
  obtainProfileFromDb = async () : Promise<User|undefined>=>{
120
125
  const filter = { $match:{uid:this.uid,tenantId:this.tenantId} }
121
-
122
-
123
-
124
126
 
125
127
  const joinpermission:PipelineStage = {$lookup: {
126
128
  from : 'permission',
127
- localField : 'uid',
128
- foreignField : 'uid',
129
+ localField : '_id',
130
+ foreignField : 'userId',
129
131
  as : 'permissions',
130
132
  pipeline:[
131
- { $match:{
132
- uid:this.uid,
133
- tenantId:this.tenantId,
134
- orgId:this.orgId,
135
- branchId:this.branchId,
133
+ {
134
+ $match:{
135
+ // userId:this.getId(),
136
+ tenantId:this.tenantId,
137
+ orgId:this.orgId,
138
+ branchId:this.branchId,
136
139
  }},
137
140
  {$lookup:{from: 'branch',localField: 'branchId',foreignField:'branchId',as: 'currentbranch'}},
138
141
  {$lookup:{from: 'organization',localField: 'orgId',foreignField:'orgId',as: 'currentorg'}}
@@ -153,22 +156,38 @@ export class UserContext {
153
156
  // console.log("obtainProfileFromDbobtainProfileFromDb ",users)
154
157
  if(users && users.length>0){
155
158
  const userinfo = users[0]
156
- // console.log("userinfouserinfouserinfouserinfouserinfouserinfo ",userinfo)
159
+ console.log("userinfouserinfouserinfouserinfouserinfouserinfo ",userinfo)
157
160
 
158
161
  if(this.tenantId>0){
159
162
  const myperm=userinfo.permissions[0]
160
163
  if(myperm && myperm.group){
161
164
  userinfo.group = myperm.group
162
- userinfo.roles = rolegroups[userinfo.group]
165
+ userinfo.roles = rolegroups[userinfo.group]()
163
166
  userinfo.branchCode = myperm.currentbranch[0].branchCode
164
167
  userinfo.branchName = myperm.currentbranch[0].branchName
165
168
  userinfo.orgCode = myperm.currentorg[0].orgCode
166
169
  userinfo.orgName = myperm.currentorg[0].orgName
170
+
167
171
  }
168
172
  }else{
169
173
  userinfo.group = ''
170
174
  }
175
+ console.log('userinfouserinfouserinfouserinfo',userinfo)
176
+ const currentitme = new Date(this.lastActivity).getTime()
177
+ console.log(" userinfo.lastactivity userinfo.lastactivity userinfo.lastactivity ", userinfo.lastActivity )
178
+ const dblastactivity = userinfo.lastActivity ?? '2000-01-01T00:00:00Z'
179
+ const lastvisit = new Date( dblastactivity).getTime() ?? 0
180
+ // if(currentitme - lastvisit)
181
+ console.log(`${userinfo._id}: ${this.lastActivity}: ${currentitme} - ${dblastactivity}:${lastvisit} = ${currentitme - lastvisit}`)
182
+
183
+ //update last activtity dont too frequent
184
+ if(!dblastactivity || currentitme - lastvisit > 5000 ){
185
+ const newusermodel = await this.usermodel.findById(userinfo._id)
186
+ newusermodel.lastActivity= this.lastActivity
187
+ const result = await newusermodel.save()
188
+ }
171
189
 
190
+ // const result = await this.usermodel.findOneAndUpdate({_id: userinfo._id},{lastActivity: new Date().toISOString})
172
191
  return userinfo
173
192
  }else{
174
193
  return undefined
@@ -290,6 +309,7 @@ export class UserContext {
290
309
  // obtain basic user info
291
310
  const userinfo = {
292
311
  _id: this.getId() ,
312
+ sessionId:this.sessionId,
293
313
  tenantId: this.getTenantId(),
294
314
  orgId: this.getOrgId(),
295
315
  branchId: this.getBranchId(),
@@ -309,14 +329,17 @@ export class UserContext {
309
329
 
310
330
  if(this.getId()!=''){
311
331
  this.logger.debug(userinfo,"obtain permissions and invitations")
312
- const filter:PipelineStage ={ $match:{uid:this.uid }} as PipelineStage
332
+ const filter:PipelineStage ={ $match:{
333
+ uid:this.uid,
334
+ tenantId :this.tenantId
335
+ }} as PipelineStage
313
336
  const permission:PipelineStage = {$lookup: {
314
337
  from : 'permission',
315
- localField : 'uid',
316
- foreignField : 'uid',
338
+ localField : '_id',
339
+ foreignField : 'userId',
317
340
  as : 'permissions',
318
341
  pipeline:[
319
- {$match:{uid: this.uid,},},
342
+ // {$match:{userId: this.getId(),},},
320
343
  {$lookup:{from : 'branch',localField : 'branchId',foreignField : 'branchId',as : 'branch',}},
321
344
  ]
322
345
  }}
@@ -339,6 +362,7 @@ export class UserContext {
339
362
  this.logger.debug(pipeline,"getUserInfo")
340
363
  // // // const users = await usermodel.find(filter)
341
364
  const users = await this.usermodel.aggregate(pipeline)
365
+ this.logger.debug(users,'users from aggregate')
342
366
 
343
367
 
344
368
  this.invites = users[0].invites
@@ -387,13 +411,123 @@ export class UserContext {
387
411
  const o = this.ssoACL
388
412
  const ssoclient = process.env.OAUTH2_CLIENTID
389
413
  const adminRole = process.env.OAUTH2_ADMINROLE
390
- if( o[ssoclient] && o[ssoclient]['roles'] && o[ssoclient]['roles'] == adminRole ){
391
- //console.log("isadmin")
414
+ // return false
415
+ if(this.getEmail()===process.env.ADMIN_EMAIL){
416
+ return true
417
+ }
418
+ else if( o[ssoclient] && o[ssoclient]['roles'] && o[ssoclient]['roles'] == adminRole ){
392
419
  return true
393
420
  }else{
394
- //console.log("not admin")
395
421
  return false
396
422
  }
397
423
 
398
424
  }
425
+
426
+
427
+ searchInsertedRecordId(collection:string,_id:string){
428
+ return this.modifiedRecords.createds[collection].find((item)=>item===_id)
429
+ }
430
+ addInsertedRecordId(collection:string,_id:string){
431
+ if(this.modifiedRecords.createds[collection]){
432
+ this.modifiedRecords.createds[collection].push(_id)
433
+ }else{
434
+ this.modifiedRecords.createds[collection] = [_id]
435
+ }
436
+ }
437
+ addUpdatedRecordId(collection:string,_id:string){
438
+ if(this.modifiedRecords.updateds[collection]){
439
+ this.modifiedRecords.updateds[collection].push(_id)
440
+ }else{
441
+ this.modifiedRecords.updateds[collection] = [_id]
442
+ }
443
+
444
+ }
445
+ addDeletedRecordId(collection:string,_id:string){
446
+ if(this.modifiedRecords.deleteds[collection]){
447
+ this.modifiedRecords.deleteds[collection].push(_id)
448
+ }else{
449
+ this.modifiedRecords.deleteds[collection] = [_id]
450
+ }
451
+
452
+ }
453
+
454
+
455
+ async getAllTenants (){
456
+ const results = []
457
+ if(this.getId()!=''){
458
+ const filteruser:PipelineStage ={ $match:{
459
+ uid:this.uid,
460
+ tenantId :{'$gt':0}
461
+ }} as PipelineStage
462
+
463
+ const getTenantData:PipelineStage = { $lookup:{
464
+ from : 'tenant',
465
+ localField : 'tenantId',
466
+ foreignField : 'tenantId',
467
+ as : 'tenant',}}
468
+
469
+ const permission:PipelineStage = {$lookup: {
470
+ from : 'permission',
471
+ localField : '_id',
472
+ foreignField : 'userId',
473
+ as : 'permissions',
474
+ pipeline:[
475
+
476
+ {$lookup:{from : 'organization',localField : 'orgId',foreignField : 'orgId',as : 'org',}},
477
+ {$lookup:{from : 'branch',localField : 'branchId',foreignField : 'branchId',as : 'branch',}},
478
+ ]
479
+ }}
480
+
481
+ const pipelines:PipelineStage[] =[filteruser,getTenantData,permission]
482
+ // const users=[]
483
+ this.logger.warn(pipelines,"pipelines")
484
+ const users = await this.usermodel.aggregate(pipelines)
485
+
486
+ if(users){
487
+
488
+
489
+ const activeusers = users.filter((u)=>{
490
+ // console.log(u.active,'===',true, ' && ',u.tenant[0].active,'===',true)
491
+ return u.active===true && u.tenant[0].active===true
492
+ })
493
+ // return activeusers
494
+ activeusers.forEach((u)=>{
495
+
496
+ const permissions = u.permissions.filter((item:any)=>{
497
+ return item.org[0].active && item.branch[0].active
498
+ })
499
+ .map((item:any)=>{
500
+
501
+ return {
502
+ _id: item._id,
503
+ orgId: item.orgId,
504
+ branchId: item.branchId,
505
+ group: item.group,
506
+ orgCode: item.org[0].orgCode,
507
+ orgName: item.org[0].orgName,
508
+ branchCode: item.branch[0].branchCode,
509
+ branchName: item.branch[0].branchName,
510
+ xOrg: this.generateXorg(u.tenantId,item.orgId,item.branchId)
511
+ }
512
+ })
513
+
514
+
515
+
516
+
517
+ results.push({
518
+ _id: u._id,
519
+ fullname : u.fullname,
520
+ tenantId: u.tenantId,
521
+ tenantName: u.tenant[0].tenantName,
522
+ permissions: permissions
523
+ })
524
+ })
525
+
526
+ }
527
+
528
+
529
+
530
+ }
531
+ return results
532
+ }
399
533
  }
@@ -236,7 +236,7 @@ export class SimpleAppService<T extends { _id?: string }> {
236
236
  await this.hook(appuser,HookType.beforeSearch, newfilters);
237
237
  // console.log("before _find",newfilters)
238
238
  // console.log("this.doc",this.doc)
239
- const products = await this.doc.find(newfilters,projection).sort(sort);
239
+ const products = await this.doc.find(newfilters,projection,{session:appuser.getDBSession()}).sort(sort);
240
240
  // console.log("after search",products)
241
241
  const productlist = products.map((p: T) => {
242
242
  return p;
@@ -264,7 +264,7 @@ export class SimpleAppService<T extends { _id?: string }> {
264
264
 
265
265
 
266
266
  async create(appuser:UserContext, data:T) {
267
- this.audittrail.addEvent(data)
267
+
268
268
  let result;
269
269
  if(!data._id){
270
270
  data._id = crypto.randomUUID()
@@ -279,7 +279,7 @@ export class SimpleAppService<T extends { _id?: string }> {
279
279
  if(this.withDocNumberFormat && !data[this.documentIdentityCode]){
280
280
  await this.genNewDocNo(appuser,data)
281
281
  }
282
- console.log("DATA for create",data)
282
+
283
283
  await this.hook(appuser,HookType.beforeCreate, data);
284
284
 
285
285
  let isolationFilter:any = {...appuser.getCreateFilter()}
@@ -297,9 +297,10 @@ export class SimpleAppService<T extends { _id?: string }> {
297
297
 
298
298
  this.applyNestedDateTime(appuser,data,'create')
299
299
  const newdoc = new this.doc(data);
300
- await this.identifyUniqueKeys(appuser,data)
300
+ await this.identifyForeignKeys(appuser,data)
301
301
  try{
302
302
  result = await newdoc.save({session:dbsession})
303
+ appuser.addInsertedRecordId(this.documentName, result._id)
303
304
  }catch(err){
304
305
  this.logger.error(err)
305
306
  throw new InternalServerErrorException(err)
@@ -429,6 +430,8 @@ export class SimpleAppService<T extends { _id?: string }> {
429
430
  filterIsolation['_id'] = id;
430
431
  this.logger.debug('delete filter', filterIsolation);
431
432
  const result = await this.doc.deleteOne(filterIsolation).session(dbsession);
433
+
434
+ appuser.addUpdatedRecordId(this.documentName, id)
432
435
  const deleteresult = {result:result, data: deletedata}
433
436
  this.logger.debug(deleteresult, " delete result" +this.doc.collection.name,)
434
437
  // this.doc.findByIdAndDelete(id)
@@ -478,6 +481,7 @@ export class SimpleAppService<T extends { _id?: string }> {
478
481
  this.applyNestedDateTime(appuser,data,'update')
479
482
  try{
480
483
  const result = await this.doc.findOneAndUpdate(isolationFilter, data).session(dbsession);
484
+ appuser.addUpdatedRecordId(this.documentName, data._id)
481
485
  await this.hook(appuser,HookType.afterUpdate, data);
482
486
  return result;
483
487
  } catch (err) {
@@ -571,7 +575,7 @@ export class SimpleAppService<T extends { _id?: string }> {
571
575
  }
572
576
 
573
577
 
574
- async identifyUniqueKeys(appuser:UserContext,data:T){
578
+ async identifyForeignKeys(appuser:UserContext,data:T){
575
579
  /**
576
580
  * 1. looping schemas identify what foreign key exists
577
581
  * 2. loop through record obtain all foreign key value
@@ -590,9 +594,9 @@ export class SimpleAppService<T extends { _id?: string }> {
590
594
  const fks:string[] = this.foreignkeys[collectionname]
591
595
  let results:string[] = []
592
596
  fks.forEach(fieldpath=>{
593
- // console.log("fieldpath:",fieldpath,"vdata",data,vdata)
597
+ console.log("fieldpath:",fieldpath,"vdata",data,vdata)
594
598
  const tmp = jsonpath.query(vdata,fieldpath).filter((item:string)=>item!='')
595
- // console.log("tmp",tmp)
599
+ console.log("tmp",tmp)
596
600
 
597
601
  results = results.concat(tmp)
598
602
  })
@@ -600,12 +604,12 @@ export class SimpleAppService<T extends { _id?: string }> {
600
604
 
601
605
 
602
606
  if(results.length>0){
603
- console.log('tmp',results)
604
607
  if(results.length>1){
605
608
  results = uniq<string>(results)
606
609
  }
607
610
 
608
611
  keystore[collectionname]= results
612
+ console.log("keystorekeystore",keystore)
609
613
  let addfield={$addFields:{collection:collectionname}}
610
614
 
611
615
  const stagefilter:PipelineStage = {
@@ -614,23 +618,23 @@ export class SimpleAppService<T extends { _id?: string }> {
614
618
  pipelines.push(stagefilter)
615
619
  }
616
620
  })
617
- this.logger.debug(pipelines,'identifyUniqueKeys')
621
+ this.logger.log(pipelines,'identifyForeignKeys pipelines')
618
622
  // this.doc.db.collection(collectionname);
619
623
  const unionresult = await this.doc.aggregate(pipelines)
620
624
 
621
625
  if(!unionresult){
622
- this.logger.error("foreign key control failed ",'identifyUniqueKeys')
626
+ this.logger.error("foreign key control failed ",'identifyForeignKeys')
623
627
  throw new InternalServerErrorException("Foreignkey check execution error",pipelines as HttpExceptionOptions)
624
628
  }else{
625
629
  let searchresult:any = {}
626
630
  unionresult.forEach(item=>{
627
- console.log("111")
628
631
  if(searchresult[item.collection]){
629
632
  searchresult[item.collection].push(item._id)
630
633
  }else{
631
634
  searchresult[item.collection] = [item._id]
632
635
  }
633
636
  })
637
+ this.logger.log(unionresult,this.documentType+" search Result")
634
638
 
635
639
  //search is it all foreign key exists in db
636
640
  for(let i=0; i<collections.length; i++){
@@ -643,11 +647,15 @@ export class SimpleAppService<T extends { _id?: string }> {
643
647
  const key = keys[k]
644
648
  if(searchresult[collectionname] && searchresult[collectionname].includes(key)){
645
649
  this.logger.debug(`foreignkey ${collectionname}->${key} exists`)
646
- }
650
+ }
651
+ else if(appuser.searchInsertedRecordId(collectionname,key)){
652
+ this.logger.debug(`foreignkey ${collectionname} exists in user context which not yet commited`)
653
+ }
647
654
  else{
648
- this.logger.warn(`Foreignkey ${key} at collection ${collectionname} does not exist`,'identifyUniqueKeys')
655
+ this.logger.warn(`${this.documentType}: Foreignkey ${key} at collection ${collectionname} does not exist`,'identifyForeignKeys')
656
+ this.logger.log(appuser.getModifieds,"appuser.getModifieds")
649
657
  const errordata = {key:key,collection:collectionname}
650
- throw new BadRequestException(`Foreignkey ${key} at collection ${collectionname} does not exist`,JSON.stringify(errordata))
658
+ throw new BadRequestException(`${this.documentType}: Foreignkey ${key} at collection ${collectionname} does not exist`,JSON.stringify(errordata))
651
659
 
652
660
  }
653
661
  }
@@ -655,7 +663,6 @@ export class SimpleAppService<T extends { _id?: string }> {
655
663
  }
656
664
 
657
665
  }
658
- console.log("666")
659
666
  }
660
667
 
661
668
 
@@ -8,6 +8,14 @@ export type ForeignKey = {
8
8
  _id: string
9
9
  label: string
10
10
  }
11
+ export type ModifiedCollection = {
12
+ [key:string]:string[]
13
+ }
14
+ export type ModifiedRecords = {
15
+ createds: ModifiedCollection
16
+ updateds: ModifiedCollection
17
+ deleteds: ModifiedCollection
18
+ }
11
19
  export type DocNumberFormatResult = {
12
20
  formatId: string
13
21
  formatName: string
@@ -67,6 +67,31 @@ export class ProfileController {
67
67
  }
68
68
  }
69
69
 
70
+ @Get('/tenants')
71
+ @Roles(Role.Everyone, Role.User)
72
+ @ApiOperation({
73
+ operationId: 'getAllTenants',
74
+ description: 'Get all tenants',
75
+ })
76
+ @ApiResponse({
77
+ status: 200,
78
+ type: () => [MyProfileApiSchema],
79
+ description: 'Success',
80
+ })
81
+ @ApiResponse({ status: 401, type: Object, description: 'Undefine profile' })
82
+ async getAllTenants(@AppUser() appuser: UserContext) {
83
+ this.logger.debug(
84
+ `access getAllTenants API by ${appuser.getUid()},(${appuser.getId()})`,
85
+ );
86
+ const result = await this.profileservice.getAllTenants(appuser);
87
+ this.logger.debug('getProfile result is:');
88
+ this.logger.debug(result);
89
+ if (result) {
90
+ return result;
91
+ } else {
92
+ throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
93
+ }
94
+ }
70
95
 
71
96
  @Post('/tenant')
72
97
  @Roles(Role.Everyone)
@@ -106,10 +131,8 @@ export class ProfileController {
106
131
  decision,
107
132
  );
108
133
  if (result) {
109
- console.log('result', result);
110
134
  return result;
111
135
  } else {
112
- console.log('throw error');
113
136
  throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
114
137
  }
115
138
  }
@@ -67,8 +67,6 @@ export class ProfileService {
67
67
  }
68
68
 
69
69
  async createUserProfile(appuser: UserContext) {
70
-
71
-
72
70
  const data: User = {
73
71
  uid: appuser.getUid(),
74
72
  fullname: appuser.getFullname(),
@@ -76,7 +74,11 @@ export class ProfileService {
76
74
  active: true,
77
75
  doctype: 'user',
78
76
  } as User;
79
-
77
+ if (appuser.getTenantId() == 0) {
78
+ data.tenantId = 0;
79
+ data.orgId = 0;
80
+ data.branchId = 0;
81
+ }
80
82
  const createresult = await this.usersvc.create(appuser, data);
81
83
  const userinfo = await appuser.getUserInfo();
82
84
  userinfo._id = createresult._id;
@@ -85,7 +87,7 @@ export class ProfileService {
85
87
 
86
88
  async createTenant(appuser: UserContext, tenantName: string) {
87
89
  // try{
88
- appuser.getDBSession().startTransaction()
90
+ appuser.getDBSession().startTransaction();
89
91
  const tenantdata: Tenant = {
90
92
  tenantId: 1,
91
93
  tenantName: tenantName,
@@ -112,7 +114,7 @@ export class ProfileService {
112
114
  orgCode: 'HQ',
113
115
  orgId: 1,
114
116
  };
115
-
117
+
116
118
  this.logger.log(orgdata, 'createOrg data');
117
119
  const orgResult = await this.orgsvc.create(appuser, orgdata);
118
120
  if (!orgResult) {
@@ -131,7 +133,7 @@ export class ProfileService {
131
133
  organization: { _id: orgRecordId, label: tenantName },
132
134
  };
133
135
  this.logger.log(branchdata, 'createbranch data');
134
-
136
+
135
137
  const branchResult = await this.branchsvc.create(appuser, branchdata);
136
138
  if (!branchResult) {
137
139
  throw new BadRequestException('Create Branch failed');
@@ -163,6 +165,7 @@ export class ProfileService {
163
165
  orgId: orgResult.orgId,
164
166
  branchId: branchResult.branchId,
165
167
  uid: appuser.getUid(),
168
+ userId: userRecordId,
166
169
  group: 'admin',
167
170
  };
168
171
  this.logger.log(permdata, 'create Permission data');
@@ -173,6 +176,16 @@ export class ProfileService {
173
176
 
174
177
  this.logger.log(permResult, 'create Permission result');
175
178
 
179
+
180
+ //tenant owner shall map to userId for that tenant
181
+
182
+ const tenantUpdateData = await this.tenantsvc.findById(appuser,tenantResult._id)
183
+ this.logger.log(tenantUpdateData, `update tenant owner(${tenantResult._id})`);
184
+ tenantUpdateData.owner._id = userRecordId
185
+ const updateTenantOwnerResult = await this.tenantsvc.findIdThenUpdate(appuser,tenantResult._id,tenantUpdateData)
186
+ if (!updateTenantOwnerResult) {
187
+ throw new BadRequestException('Update tenant owner failed');
188
+ }
176
189
  const xorg: string = Base64URL.encodeText(
177
190
  `${tenantResult.tenantId}-${orgResult.orgId}-${branchResult.branchId}`,
178
191
  );
@@ -198,4 +211,8 @@ export class ProfileService {
198
211
  async decideInvitation(appuser: UserContext, id: string, decision: string) {
199
212
  return await appuser.decideInvitation(id, decision);
200
213
  }
214
+
215
+ async getAllTenants(appuser: UserContext) {
216
+ return await appuser.getAllTenants();
217
+ }
201
218
  }
@@ -9,19 +9,19 @@ import { Model } from 'mongoose';
9
9
  import { Injectable, InternalServerErrorException } from '@nestjs/common';
10
10
  import { BranchProcessor } from '../generate/processors/branch.processor';
11
11
  import { Branch } from '../generate/types/branch.type';
12
- import {alldocuments} from '../generate/commons/dicts/documents'
12
+ import { alldocuments } from '../generate/commons/dicts/documents';
13
13
  export { Branch } from '../generate/types/branch.type';
14
14
  import { AutoincreamentService } from './autoinc.service';
15
15
  import { UserContext } from '../generate/commons/user.context';
16
- import { Docnoformat,DocnoformatService } from './docno.service';
16
+ import { Docnoformat, DocnoformatService } from './docno.service';
17
17
  // import { Docnoformat } from '../generate/types/docno.type';
18
18
  @Injectable()
19
19
  export class BranchService extends BranchProcessor {
20
20
  protected strictIsolation = false;
21
21
  constructor(
22
22
  @InjectModel('Branch') mydoc: Model<Branch>,
23
- private increament: AutoincreamentService,
24
- private docnoservice:DocnoformatService
23
+ private increament: AutoincreamentService,
24
+ private docnoservice: DocnoformatService,
25
25
  ) {
26
26
  super(mydoc);
27
27
  }
@@ -46,9 +46,9 @@ export class BranchService extends BranchProcessor {
46
46
  );
47
47
  data.branchId = searchresult.nextno;
48
48
  break;
49
- case 'afterCreate':
50
- await this.generateDefaultDocNumbers(appuser,data);
51
- break;
49
+ case 'afterCreate':
50
+ await this.generateDefaultDocNumbers(appuser, data);
51
+ break;
52
52
  // case 'beforeUpdate':
53
53
  // break;
54
54
  // case 'afterUpdate':
@@ -67,40 +67,41 @@ export class BranchService extends BranchProcessor {
67
67
  return true;
68
68
  };
69
69
 
70
- generateDefaultDocNumbers =async (appuser,data) => {
71
- const branchName = data.branchName
72
- const branchCode = data.branchCode
73
- const recordId = data._id
74
- const branchId= data.branchId
75
- const orgId = data.orgId
76
- const tenantId = data.tenantId
77
- const docformats = alldocuments.filter((item)=>item.docNumber)
78
- for(let i=0; i< docformats.length; i++){
79
- const doc = docformats[i]
80
- const pattern = `${doc.docType}-${branchCode}-[00000]`
81
- const formatdata:Docnoformat = {
82
- _id:crypto.randomUUID(),
83
- docNoFormatNo:'Default',
84
- docNoFormatName:'Default',
70
+ generateDefaultDocNumbers = async (appuser, data) => {
71
+ const branchName = data.branchName;
72
+ const branchCode = data.branchCode;
73
+ const recordId = data._id;
74
+ const branchId = data.branchId;
75
+ const orgId = data.orgId;
76
+ const tenantId = data.tenantId;
77
+ const docformats = alldocuments.filter((item) => item.docNumber);
78
+ for (let i = 0; i < docformats.length; i++) {
79
+ const doc = docformats[i];
80
+ const pattern = `${doc.docType}-${branchCode}-[00000]`;
81
+ const formatdata: Docnoformat = {
82
+ _id: crypto.randomUUID(),
83
+ docNoFormatNo: doc.docType,
84
+ docNoFormatName: `Default ${doc.docType}`,
85
85
  docNoType: doc.docType,
86
- docNoPattern: pattern,
87
- branch:{_id:recordId,branchId:branchId,label:branchName},
88
- branchId:branchId,
89
- orgId:orgId,
90
- tenantId:tenantId,
91
- nextNumber:1,
92
- } as Docnoformat
93
- try{
94
- const result = await this.docnoservice.create(appuser,formatdata)
95
- if(!result){
96
- throw new InternalServerErrorException(`Generate default document number for "${branchCode}" failed. Pattern: ${pattern}`,'generateDefaultDocNumbers')
86
+ docNoPattern: pattern,
87
+ branch: { _id: recordId, branchId: branchId, label: branchName },
88
+ branchId: branchId,
89
+ orgId: orgId,
90
+ tenantId: tenantId,
91
+ nextNumber: 1,
92
+ } as Docnoformat;
93
+ try {
94
+ const result = await this.docnoservice.create(appuser, formatdata);
95
+ if (!result) {
96
+ throw new InternalServerErrorException(
97
+ `Generate default document number for "${branchCode}" failed. Pattern: ${pattern}`,
98
+ 'generateDefaultDocNumbers',
99
+ );
97
100
  }
98
-
99
- }catch(err){
100
- this.logger.error(err)
101
- throw new InternalServerErrorException(err)
101
+ } catch (err) {
102
+ this.logger.error(err);
103
+ throw new InternalServerErrorException(err);
102
104
  }
103
-
104
- }
105
- }
105
+ }
106
+ };
106
107
  }