diff --git a/.azure/pipelines/Phonebook.preview.yml b/.azure/pipelines/Phonebook.preview.yml index 220e9a951..ad2ebdbdc 100644 --- a/.azure/pipelines/Phonebook.preview.yml +++ b/.azure/pipelines/Phonebook.preview.yml @@ -6,7 +6,8 @@ pr: variables: image_repo: tsystemsmms image_namespace: phonebook-build - image_tag: pr-$(System.PullRequest.PullRequestNumber) + image_tag_frontend: pr-$(System.PullRequest.PullRequestNumber) + image_tag_source_peoplesoft: pr-$(System.PullRequest.PullRequestNumber)-peoplesoft helm_artifact_name: HelmPhonebookPackage jobs: @@ -19,23 +20,46 @@ jobs: inputs: version: '12.x' - - script: node version.js $(image_tag) $(Build.SourceVersion) $(Build.SourceVersion) + - script: node version.js $(image_tag_frontend) $(Build.SourceVersion) $(Build.SourceVersion) displayName: 'Write Version Number' workingDirectory: 'Phonebook.Frontend/' - - script: docker build -t $(image_repo)/$(image_namespace):$(image_tag) . + - script: docker build -t $(image_repo)/$(image_namespace):$(image_tag_frontend) . displayName: 'Build Image' workingDirectory: 'Phonebook.Frontend/' - script: | docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD - docker push $(image_repo)/$(image_namespace):$(image_tag) + docker push $(image_repo)/$(image_namespace):$(image_tag_frontend) workingDirectory: 'Phonebook.Frontend/' displayName: 'Push Image' env: DOCKER_REGISTRY_PASSWORD: $(DOCKER_REGISTRY_PASSWORD) DOCKER_REGISTRY_USER: $(DOCKER_REGISTRY_USER) + - job: build_phonebook_source_peoplesoft + displayName: 'Phonebook Source Peoplesoft' + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: UseNode@1 + inputs: + version: '12.x' + + + - script: docker build -t $(image_repo)/$(image_namespace):$(image_tag_source_peoplesoft) . + displayName: 'Build Image' + workingDirectory: 'Phonebook.Source.PeopleSoft/' + + - script: | + docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD + docker push $(image_repo)/$(image_namespace):$(image_tag_source_peoplesoft) + workingDirectory: 'Phonebook.Source.PeopleSoft/' + displayName: 'Push Image' + env: + DOCKER_REGISTRY_PASSWORD: $(DOCKER_REGISTRY_PASSWORD) + DOCKER_REGISTRY_USER: $(DOCKER_REGISTRY_USER) + - job: build_phonebook_helm displayName: Phonebook Helm Chart pool: @@ -63,7 +87,7 @@ jobs: pool: vmImage: 'ubuntu-16.04' variables: - namespace: $(image_tag) + namespace: $(image_tag_frontend) steps: - download: current artifact: $(helm_artifact_name) @@ -98,7 +122,7 @@ jobs: chartType: FilePath chartPath: '$(Pipeline.Workspace)/$(helm_artifact_name)/phonebook-0.1.0.tgz' releaseName: phonebook-$(namespace) - overrideValues: 'frontend.image.tag=$(image_tag),frontend.image.repository=$(image_repo),frontend.image.name=$(image_namespace),traefik.enabled=false,host=$(image_tag).demo-phonebook.me' + overrideValues: 'frontend.image.tag=$(image_tag_frontend),frontend.image.repository=$(image_repo),frontend.image.name=$(image_namespace),source.peoplesoft.image.tag=$(image_tag_source_peoplesoft),source.peoplesoft.image.name=$(image_namespace),traefik.enabled=false,host=$(image_tag_frontend).demo-phonebook.me' valueFile: 'demo/values.yml' recreate: true tillerNamespace: kube-system @@ -128,7 +152,7 @@ jobs: } body: | { - "body": "Preview Environment ready at https://$(image_tag).demo-phonebook.me" + "body": "Preview Environment ready at https://$(image_tag_frontend).demo-phonebook.me" } urlSuffix: 'repos/T-Systems-MMS/phonebook/issues/$(System.PullRequest.PullRequestNumber)/comments' waitForCompletion: 'false' @@ -153,7 +177,7 @@ jobs: pool: vmImage: 'ubuntu-16.04' variables: - namespace: $(image_tag) + namespace: $(image_tag_frontend) steps: - checkout: none - task: HelmInstaller@1 diff --git a/Phonebook.Frontend/src/app/modules/organigram/organigram-routing.module.ts b/Phonebook.Frontend/src/app/modules/organigram/organigram-routing.module.ts index 67c08fcb5..d4ee17414 100644 --- a/Phonebook.Frontend/src/app/modules/organigram/organigram-routing.module.ts +++ b/Phonebook.Frontend/src/app/modules/organigram/organigram-routing.module.ts @@ -9,6 +9,7 @@ const routes: Routes = [ { path: ':first/:second/:third', component: OrganigramComponent }, { path: ':first/:second/:third/:fourth', component: OrganigramComponent }, { path: ':first/:second/:third/:fourth/:fifth', component: OrganigramComponent }, + { path: ':first/:second/:third/:fourth/:fifth/:sixth', component: OrganigramComponent }, ]; @NgModule({ diff --git a/Phonebook.Frontend/src/app/modules/table/table-logic.spec.ts b/Phonebook.Frontend/src/app/modules/table/table-logic.spec.ts index 047396c60..189dece27 100644 --- a/Phonebook.Frontend/src/app/modules/table/table-logic.spec.ts +++ b/Phonebook.Frontend/src/app/modules/table/table-logic.spec.ts @@ -24,7 +24,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), new Person( PersonStatus.Interner_Mitarbeiter, @@ -36,7 +36,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]; expect( @@ -55,7 +55,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), new Person( PersonStatus.Interner_Mitarbeiter, @@ -67,7 +67,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]); }); @@ -83,7 +83,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), new Person( PersonStatus.Interner_Mitarbeiter, @@ -95,7 +95,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]; @@ -115,7 +115,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), new Person( PersonStatus.Interner_Mitarbeiter, @@ -127,7 +127,7 @@ describe('Table Logic - Sort', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]); }); @@ -146,7 +146,7 @@ describe('Table Logic - Filter', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]; expect( @@ -162,7 +162,7 @@ describe('Table Logic - Filter', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]); }); @@ -179,7 +179,7 @@ describe('Table Logic - Filter', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]; expect( @@ -199,7 +199,7 @@ describe('Table Logic - Filter', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]; expect( @@ -219,7 +219,7 @@ describe('Table Logic - Filter', () => { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), []), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ), ]); }); diff --git a/Phonebook.Frontend/src/app/services/api/organigram.service.spec.ts b/Phonebook.Frontend/src/app/services/api/organigram.service.spec.ts index b904bf24c..ff6b21923 100644 --- a/Phonebook.Frontend/src/app/services/api/organigram.service.spec.ts +++ b/Phonebook.Frontend/src/app/services/api/organigram.service.spec.ts @@ -1,11 +1,16 @@ import { inject, TestBed } from '@angular/core/testing'; import { OrganigramService } from './organigram.service'; import { PersonService } from './person.service'; +import { HttpClient } from '@angular/common/http'; describe('OrganigramService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [OrganigramService, { provide: PersonService, useValue: null }], + providers: [ + OrganigramService, + { provide: PersonService, useValue: null }, + { provide: HttpClient, useValue: null }, + ], }); }); diff --git a/Phonebook.Frontend/src/app/services/api/organigram.service.ts b/Phonebook.Frontend/src/app/services/api/organigram.service.ts index 5470affb9..c81ef15de 100644 --- a/Phonebook.Frontend/src/app/services/api/organigram.service.ts +++ b/Phonebook.Frontend/src/app/services/api/organigram.service.ts @@ -1,70 +1,62 @@ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { Observable, forkJoin, of } from 'rxjs'; +import { map, flatMap, publishReplay, refCount } from 'rxjs/operators'; import { Person } from 'src/app/shared/models'; import { PersonService } from './person.service'; +import { HttpClient } from '@angular/common/http'; @Injectable() export class OrganigramService { - constructor(private personService: PersonService) {} - + constructor(private http: HttpClient, private personService: PersonService) {} + public organigram: Observable; public getOrganigram(): Observable { - return this.personService.getAll().pipe( - map((users) => { - const tree: UnitTreeNode[] = []; - users.forEach((person) => { - if (person.Business.ShortOrgUnit.length === 0) { - return; - } - this.findNodeForPerson(person, tree, 0); - }); - return tree; - }) - ); - } - - /** - * Finds the Person's Node in the Hierarchical Structure of Units (generates the Units along its way.) - * @param person The person for whom you like to find the node - * @param nodeChilds The Childs of the node your are currently searching in. - * @param depth The depth of the Tree (to map the Persons Array of Units to the Tree structure) - */ - public findNodeForPerson(person: Person, nodeChilds: UnitTreeNode[], depth: number) { - const firstnode = nodeChilds.find((node) => { - return node.id === person.Business.ShortOrgUnit[depth]; - }); - if (firstnode === undefined) { - const newNode = new UnitTreeNode( - person.Business.ShortOrgUnit[depth], - person.Business.OrgUnit[depth], - depth - ); - if (depth === person.Business.ShortOrgUnit.length - 1) { - this.pushToSpecificGroup(newNode, person); - } else if (person.Business.ShortOrgUnit.length - 1 > depth) { - this.findNodeForPerson(person, newNode.children, depth + 1); - } - nodeChilds.push(newNode); - } else { - if (depth === person.Business.ShortOrgUnit.length - 1) { - this.pushToSpecificGroup(firstnode, person); - return; - } else { - this.findNodeForPerson(person, firstnode.children, depth + 1); - } + if (this.organigram != null) { + return this.organigram; } + this.organigram = this.http.get('/api/OrgUnit').pipe( + flatMap((d) => this.ConvertOrgUnitsToUnitTree(d)), + publishReplay(1), // this tells Rx to cache the latest emitted + refCount() + ); + return this.organigram; } - - public pushToSpecificGroup(node: UnitTreeNode, person: Person) { - if (person.isLearner()) { - node.learners.push(person); - } else if (person.isSupervisor()) { - node.supervisors.push(person); - } else if (person.isAssistent()) { - node.assistents.push(person); - } else { - node.employees.push(person); - } + private ConvertOrgUnitsToUnitTree( + orgUnits: OrgUnit[], + depth: number = 0 + ): Observable { + return forkJoin( + orgUnits.map((o) => { + var TaShortNames = o.OrgUnitToFunctions.filter((f) => f.RoleName == 'TA').map( + (t) => t.Person.ShortName + ); + return forkJoin( + o.ChildOrgUnits == null || o.ChildOrgUnits.length == 0 + ? of([]) + : this.ConvertOrgUnitsToUnitTree(o.ChildOrgUnits, depth + 1), + o.HeadOfOrgUnit == null + ? of(null) + : this.personService.getById(o.HeadOfOrgUnit.ShortName), + TaShortNames.length == 0 + ? of([]) + : forkJoin(TaShortNames.map((shortName) => this.personService.getById(shortName))), + o.ShortName == null ? of([]) : this.personService.getByOrgUnit(o.ShortName) + ).pipe( + map(([childs, headofOrgUnit, assistents, members]) => { + var tree = new UnitTreeNode( + o.ShortName == null ? '' : o.ShortName, + o.Name == null ? '' : o.Name, + depth, + o.ChildOrgUnits == null ? [] : childs, + headofOrgUnit == null ? [] : [headofOrgUnit], + assistents.filter((a) => a != null) as Person[], + members.filter((p) => p.isLearner() == false), + members.filter((p) => p.isLearner()) + ); + return tree; + }) + ); + }) + ); } } @@ -97,3 +89,30 @@ export class UnitTreeNode { this.learners = learners; } } + +class OrgUnit { + public Id: number; + + public Name?: string; + + public ShortName?: string; + + public ParentId?: number; + public Parent?: OrgUnit; + public ChildOrgUnits?: OrgUnit[]; + + public HeadOfOrgUnitId?: number; + + public HeadOfOrgUnit?: { + ShortName: string; + }; + + public CostCenter?: string; + public OrgUnitToFunctions: { + PersonId?: number; + Person: { + ShortName: string; + }; + RoleName: string; + }[]; +} diff --git a/Phonebook.Frontend/src/app/services/api/person.service.ts b/Phonebook.Frontend/src/app/services/api/person.service.ts index 2df128d2e..ca8f8bc20 100644 --- a/Phonebook.Frontend/src/app/services/api/person.service.ts +++ b/Phonebook.Frontend/src/app/services/api/person.service.ts @@ -65,6 +65,7 @@ export class PersonService { item.Location.LinkRoutingInfo ), new Business( + item.Business.Id, item.Business.ShortBusinessunitTeamassistent, item.Business.ShortSupervisor, item.Business.ShortOrgUnit, @@ -110,6 +111,17 @@ export class PersonService { ); } + public getByOrgUnit(name: string): Observable { + return this.getAll().pipe( + map((personArray) => { + return personArray.filter((p) => { + var personOrgUnit = p.Business.ShortOrgUnit[p.Business.ShortOrgUnit.length - 1]; + return personOrgUnit == name; + }); + }) + ); + } + public getPersonsByRoom(roomId: string): Observable { return this.getAll().pipe( map((personArray) => { diff --git a/Phonebook.Frontend/src/app/shared/config/ColumnDefinitions.spec.ts b/Phonebook.Frontend/src/app/shared/config/ColumnDefinitions.spec.ts index a7a36a903..d8da7623b 100644 --- a/Phonebook.Frontend/src/app/shared/config/ColumnDefinitions.spec.ts +++ b/Phonebook.Frontend/src/app/shared/config/ColumnDefinitions.spec.ts @@ -22,7 +22,7 @@ const personA = new Person( false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', '', ''), [new Room('', '', 0, '', '', '', '', '', '')]), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ); const personB = new Person( @@ -35,7 +35,7 @@ const personB = new Person( false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', '', ''), [new Room('', '', 0, '', '', '', '', '', '')]), - new Business([], [], [], [], [], [], '') + new Business(null, [], [], [], [], [], [], '') ); describe('Column Filter Functions: ', () => { diff --git a/Phonebook.Frontend/src/app/shared/mocks/person.ts b/Phonebook.Frontend/src/app/shared/mocks/person.ts index 0e7435f56..4c2fd87c9 100644 --- a/Phonebook.Frontend/src/app/shared/mocks/person.ts +++ b/Phonebook.Frontend/src/app/shared/mocks/person.ts @@ -45,6 +45,7 @@ export const mockPerson: Person = new Person( ], }, { + Id: null, ShortBusinessunitTeamassistent: ['ABC'], ShortSupervisor: ['ABC'], ShortOrgUnit: ['AB_1', 'AD CD', 'AB CD'], diff --git a/Phonebook.Frontend/src/app/shared/models/classes/Business.ts b/Phonebook.Frontend/src/app/shared/models/classes/Business.ts index 3f3b9eb5b..071610f25 100644 --- a/Phonebook.Frontend/src/app/shared/models/classes/Business.ts +++ b/Phonebook.Frontend/src/app/shared/models/classes/Business.ts @@ -1,6 +1,7 @@ /* tslint:disable:variable-name */ export class Business { + public Id: number; public ShortBusinessunitTeamassistent: string[]; public ShortSupervisor: string[]; public ShortOrgUnit: string[]; @@ -10,6 +11,7 @@ export class Business { public Costcenter: string; constructor( + Id: number, shortBusinessunitTeamassistent: string[], shortSupervisor: string[], shortOrgUnit: string[], @@ -18,6 +20,7 @@ export class Business { supervisor: string[], costcenter: string ) { + this.Id = Id; this.ShortBusinessunitTeamassistent = shortBusinessunitTeamassistent; this.ShortSupervisor = shortSupervisor; this.ShortOrgUnit = shortOrgUnit; diff --git a/Phonebook.Frontend/src/app/shared/models/classes/Person.ts b/Phonebook.Frontend/src/app/shared/models/classes/Person.ts index 8a06947c5..4c3bf021b 100644 --- a/Phonebook.Frontend/src/app/shared/models/classes/Person.ts +++ b/Phonebook.Frontend/src/app/shared/models/classes/Person.ts @@ -69,7 +69,7 @@ export class Person { false, new Contacts('', '', '', '', new Messenger('', 0)), new Location(new City('', ''), [new Room('', '', 0, '', '', '', '', '', '')]), - new Business([], [], [], [], [], [], '') + new Business(NaN, [], [], [], [], [], [], '') ); } } diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Context/ModelContext.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Context/ModelContext.cs index 20d246850..9257acf45 100644 --- a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Context/ModelContext.cs +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Context/ModelContext.cs @@ -96,6 +96,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .ToTable("V_ORGEINHEIT") .HasMany(o => o.Members) .WithOne(p => p.OrgUnit); + modelBuilder + .Entity() + .ToTable("V_ORGEINHEIT") + .HasMany(o => o.ChildOrgUnits) + .WithOne(p => p.Parent); modelBuilder .Entity() .ToTable("V_ORGEINHEIT") diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Old/Business.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Old/Business.cs index 8c28ab21f..5839d8033 100644 --- a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Old/Business.cs +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/Old/Business.cs @@ -3,40 +3,36 @@ using System.Linq; using System.Threading.Tasks; -namespace Phonebook.Source.PeopleSoft.Models.Old -{ - public class Business - { +namespace Phonebook.Source.PeopleSoft.Models.Old { + public class Business { private readonly OrgUnit orgUnit; private readonly IEnumerable orgUnitStructur; - public Business(Models.OrgUnit orgUnit, bool forOwners = false) - { + public Business (Models.OrgUnit orgUnit, bool forOwners = false) { this.orgUnit = orgUnit; var currentOrgUnit = orgUnit; - var orgUnitStructur = new List(); - orgUnitStructur.Add(orgUnit); - while (currentOrgUnit.Parent != null) - { - orgUnitStructur.Add(currentOrgUnit.Parent); + var orgUnitStructur = new List (); + orgUnitStructur.Add (orgUnit); + do { + orgUnitStructur.Add (currentOrgUnit.Parent); currentOrgUnit = currentOrgUnit.Parent; - } - orgUnitStructur.Reverse(); + } while (currentOrgUnit != null && currentOrgUnit.Parent != null); + orgUnitStructur.Reverse (); this.orgUnitStructur = orgUnitStructur; - if (forOwners) - { - var newHeadOf = orgUnitStructur.ElementAt(orgUnitStructur.Count - 2).HeadOfOrgUnit; - var changeOwner = orgUnitStructur.Last(); + if (forOwners) { + var newHeadOf = orgUnitStructur.ElementAt (orgUnitStructur.Count - 2).HeadOfOrgUnit; + var changeOwner = orgUnitStructur.Last (); changeOwner.HeadOfOrgUnit = newHeadOf; changeOwner.HeadOfOrgUnitId = newHeadOf?.Id; } } - public IEnumerable? ShortBusinessunitTeamassistent { get { return orgUnit?.OrgUnitToFunctions?.Where(d => d.RoleName == "TA")?.Select(d => d?.Person?.ShortName); } } - public IEnumerable? ShortSupervisor { get { return new string?[] { orgUnitStructur?.Where(d => d?.Id != 110 && !string.IsNullOrWhiteSpace(d?.HeadOfOrgUnit?.ShortName)).Select(d => d?.HeadOfOrgUnit?.ShortName).LastOrDefault() }; } } - public IEnumerable? ShortOrgUnit { get { return orgUnitStructur?.Where(d => d?.Id != 110 && string.IsNullOrWhiteSpace(d?.HeadOfOrgUnit?.ShortName) == false).Select(d => d?.ShortName); } } - public IEnumerable? OrgUnit { get { return orgUnitStructur?.Where(d => d?.Id != 110 && d?.HeadOfOrgUnit != null).Select(d => d?.Name); } } - public IEnumerable BusinessunitTeamassistent { get { return orgUnit.OrgUnitToFunctions.Where(d => d.RoleName == "TA").Select(d => $"{d.Person.FirstName} {d.Person.LastName}"); } } - public IEnumerable Supervisor { get { return new string[] { orgUnitStructur.Where(d => d.Id != 110 && string.IsNullOrWhiteSpace(d?.HeadOfOrgUnit?.FirstName) == false && string.IsNullOrWhiteSpace(d?.HeadOfOrgUnit?.LastName) == false).Select(d => $"{d?.HeadOfOrgUnit?.FirstName} {d?.HeadOfOrgUnit?.LastName}").LastOrDefault() }; } } + public int Id { get { return orgUnit.Id; } } + public IEnumerable ? ShortBusinessunitTeamassistent { get { return orgUnit?.OrgUnitToFunctions?.Where (d => d.RoleName == "TA")?.Select (d => d?.Person?.ShortName); } } + public IEnumerable ? ShortSupervisor { get { yield return orgUnitStructur?.Where (d => !string.IsNullOrWhiteSpace (d?.HeadOfOrgUnit?.ShortName)).Select (d => d?.HeadOfOrgUnit?.ShortName).LastOrDefault (); } } + public IEnumerable ? ShortOrgUnit { get { return orgUnitStructur?.Where (d => d?.HeadOfOrgUnit != null).Select (d => d?.ShortName); } } + public IEnumerable ? OrgUnit { get { return orgUnitStructur?.Where (d => d?.HeadOfOrgUnit != null).Select (d => d?.Name); } } + public IEnumerable BusinessunitTeamassistent { get { return orgUnit.OrgUnitToFunctions.Where (d => d.RoleName == "TA").Select (d => $"{d.Person.FirstName} {d.Person.LastName}"); } } + public IEnumerable Supervisor { get { yield return orgUnitStructur.Where (d => string.IsNullOrWhiteSpace (d?.HeadOfOrgUnit?.FirstName) == false && string.IsNullOrWhiteSpace (d?.HeadOfOrgUnit?.LastName) == false).Select (d => $"{d?.HeadOfOrgUnit?.FirstName} {d?.HeadOfOrgUnit?.LastName}").LastOrDefault (); } } public string? Costcenter { get { return orgUnit?.CostCenter; } } } } diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnit.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnit.cs index 5d9a5521b..39fb209e5 100644 --- a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnit.cs +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnit.cs @@ -14,6 +14,7 @@ public class OrgUnit [Column(name:"VATER")] public int? ParentId { get; set; } public virtual OrgUnit? Parent { get; set; } + public virtual IEnumerable? ChildOrgUnits { get; set; } [Column(name: "LEITER_ORG_EINHEIT")] public int? HeadOfOrgUnitId { get; set; } diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnitToFunction.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnitToFunction.cs index ad8ae2c79..ec5f22538 100644 --- a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnitToFunction.cs +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft.Models/OrgUnitToFunction.cs @@ -14,7 +14,7 @@ public class OrgUnitToFunction public virtual Person Person { get; set; } [Column(name: "ORG_EINHEIT_ID")] public int? OrgUnitId { get; set; } - public virtual OrgUnit OrgUnit { get; set; } + public virtual OrgUnit? OrgUnit { get; set; } [Column(name: "FUNKTIONSROLLE_ID")] public int? FunctionId { get; set; } public virtual Function? Function { get; set; } diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Controllers/OrgUnitController.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Controllers/OrgUnitController.cs index b23e4e9a6..3c51b4f42 100644 --- a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Controllers/OrgUnitController.cs +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Controllers/OrgUnitController.cs @@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore; using Phonebook.Source.PeopleSoft.Models; using Phonebook.Source.PeopleSoft.Models.Context; +using Phonebook.Source.PeopleSoft.Repositories; namespace Phonebook.Source.PeopleSoft.Controllers { @@ -13,9 +14,9 @@ namespace Phonebook.Source.PeopleSoft.Controllers [Authorize] public class OrgUnitController : ControllerBase { - public ModelContext Context { get; } + public IRepository Context { get; } - public OrgUnitController(ModelContext context) + public OrgUnitController(IRepository context) { Context = context; } @@ -23,7 +24,7 @@ public OrgUnitController(ModelContext context) [HttpGet] public IEnumerable Get() { - return this.inlcudeDependencies(Context.OrgUnits); + return Context.Get(); } @@ -31,16 +32,7 @@ public IEnumerable Get() [HttpGet("{id}")] public OrgUnit Get(int id) { - return this.inlcudeDependencies(Context.OrgUnits).First(o => o.Id == id); - } - - private IQueryable inlcudeDependencies(IQueryable query) - { - return query - .AsNoTracking() - .Include(o => o.Members) - .Include(o => o.Parent); - - } + return Context.Get(id); + } } } diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Repositories/IRepository.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Repositories/IRepository.cs new file mode 100644 index 000000000..bd5eb9337 --- /dev/null +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Repositories/IRepository.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Phonebook.Source.PeopleSoft.Repositories +{ + public interface IRepository where T: class + { + IEnumerable Get(); + T Get(int id); + + } +} diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Repositories/OrgUnitRepository.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Repositories/OrgUnitRepository.cs new file mode 100644 index 000000000..8bc14e614 --- /dev/null +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Repositories/OrgUnitRepository.cs @@ -0,0 +1,71 @@ +using Microsoft.EntityFrameworkCore; +using Phonebook.Source.PeopleSoft.Models; +using Phonebook.Source.PeopleSoft.Models.Context; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Phonebook.Source.PeopleSoft.Repositories +{ + public class OrgUnitRepository: IRepository + { + private readonly ModelContext context; + + public OrgUnitRepository(ModelContext context) + { + this.context = context; + } + + public IEnumerable Get() + { + var orgUnits = this.inlcudeDependencies(context.OrgUnits).Where(o => o.ParentId == null); + return orgUnits.Select(o => GetCleanedOrgUnit(o)); + //.Select(d => GetCleanedOrgUnit(d)); + } + + public OrgUnit Get(int id) + { + var orgunit = this.inlcudeDependencies(context.OrgUnits).Single(d => d.Id == id); + //return orgunit; + return GetCleanedOrgUnit(orgunit); + } + + private OrgUnit GetCleanedOrgUnit(OrgUnit orgUnit) + { + //orgUnit.Members = orgUnit.Members.Select(d => GetCleanedPerson(d)); + orgUnit.HeadOfOrgUnit = orgUnit.HeadOfOrgUnit == null ? null : GetCleanedPerson(orgUnit.HeadOfOrgUnit); + orgUnit.OrgUnitToFunctions = orgUnit.OrgUnitToFunctions == null ? null : + orgUnit.OrgUnitToFunctions.Select(f => + { + f.OrgUnit = null; + f.Person = GetCleanedPerson(f.Person); + return f; + }); + orgUnit.ChildOrgUnits = orgUnit.ChildOrgUnits.Select(o => GetCleanedOrgUnit(o)); + orgUnit.Parent = null; + return orgUnit; + } + + private Person GetCleanedPerson(Person person) + { + person.OwnedOrgUnits = null; + person.OrgUnit = null; + person.OrgUnitFunctions = null; + return person; + } + + private ICollection inlcudeDependencies(IQueryable query) + { + return query + .AsNoTracking() + .Include(o => o.ChildOrgUnits) + .Include(o => o.OrgUnitToFunctions) + .ThenInclude(o => o.Person) + .Include(o => o.HeadOfOrgUnit) + .ToList() // We need this always. If you remove this line you don't get the tree of the orgunit... + ; + + } + } +} diff --git a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Startup.cs b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Startup.cs index e37f98ce8..0e823231f 100644 --- a/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Startup.cs +++ b/Phonebook.Source.PeopleSoft/src/Phonebook.Source.PeopleSoft/Startup.cs @@ -9,7 +9,9 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Primitives; +using Phonebook.Source.PeopleSoft.Models; using Phonebook.Source.PeopleSoft.Models.Context; +using Phonebook.Source.PeopleSoft.Repositories; using Phonebook.Source.PeopleSoft.HealthChecks; using System; using System.Collections.Generic; @@ -67,6 +69,11 @@ public void ConfigureServices(IServiceCollection services) ); } + // Repository registration + services.AddScoped, OrgUnitRepository>(); + + + #if DEBUG Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true; #endif @@ -105,7 +112,7 @@ private void AddWsFederation(IServiceCollection services) // Wtrealm is the app's identifier in the Active Directory instance. - // For ADFS, use the relying party's identifier, its WS-Federation Passive protocol URL: + // For ADFS, use the relying party's identifier, its WS-Federation Passive protocol URL: options.Wtrealm = $"{appId}"; // maybe the following is requiered for azure. check this alter.