From 7c35ff0aecf4babf11b995947a6cf8b2851277cf Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 11 Mar 2025 07:19:55 +0100
Subject: [PATCH 01/47] OZG-7473 add target field path field

- Move components declarations to imports in tests.
- Rename and move components.

Sub task: OZG-7882
---
 ...atistik-fields-form-page.component.spec.ts |  4 +-
 .../statistik-fields-form-page.component.ts   |  4 +-
 alfa-client/libs/admin/statistik/src/index.ts |  2 +-
 ...atistik-fields-form-mapping.component.html | 29 ------
 ...statistik-fields-form-mapping.component.ts | 29 ------
 ...l => statistik-fields-form.component.html} |  4 +-
 ...> statistik-fields-form.component.spec.ts} | 20 ++--
 ....ts => statistik-fields-form.component.ts} | 11 +--
 ...tatistik-field-mapping-form.component.html | 38 +++++++
 ...istik-field-mapping-form.component.spec.ts | 99 +++++++++++++++++++
 .../statistik-field-mapping-form.component.ts | 20 ++++
 ...tistik-fields-mappings-form.component.html | 10 ++
 ...ik-fields-mappings-form.component.spec.ts} | 46 ++++-----
 ...tatistik-fields-mappings-form.component.ts | 20 ++++
 .../statistik-fields.formservice.spec.ts      | 22 ++++-
 .../statistik-fields.formservice.ts           |  7 +-
 16 files changed, 250 insertions(+), 115 deletions(-)
 delete mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.html
 delete mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.ts
 rename alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/{admin-statistik-fields-form.component.html => statistik-fields-form.component.html} (94%)
 rename alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/{admin-statistik-fields-form.component.spec.ts => statistik-fields-form.component.spec.ts} (84%)
 rename alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/{admin-statistik-fields-form.component.ts => statistik-fields-form.component.ts} (69%)
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html
 rename alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/{statistik-fields-form-mapping/statistik-fields-form-mapping.component.spec.ts => statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts} (51%)
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts

diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
index 938cc1b006..5805a079fa 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
@@ -1,4 +1,4 @@
-import { AdminStatistikFieldsFormComponent } from '@admin-client/statistik';
+import { StatistikFieldsFormComponent } from '@admin-client/statistik';
 import { existsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
@@ -13,7 +13,7 @@ describe('StatistikFieldsFormPageComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [StatistikFieldsFormPageComponent, MockComponent(AdminStatistikFieldsFormComponent)],
+      imports: [StatistikFieldsFormPageComponent, MockComponent(StatistikFieldsFormComponent)],
     }).compileComponents();
 
     fixture = TestBed.createComponent(StatistikFieldsFormPageComponent);
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
index c4122b72d1..3758d1cdae 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
@@ -1,11 +1,11 @@
-import { AdminStatistikFieldsFormComponent } from '@admin-client/statistik';
+import { StatistikFieldsFormComponent } from '@admin-client/statistik';
 import { CommonModule } from '@angular/common';
 import { Component } from '@angular/core';
 
 @Component({
   selector: 'statistik-fields-form-page',
   standalone: true,
-  imports: [CommonModule, AdminStatistikFieldsFormComponent],
+  imports: [CommonModule, StatistikFieldsFormComponent],
   templateUrl: './statistik-fields-form-page.component.html',
 })
 export class StatistikFieldsFormPageComponent {}
diff --git a/alfa-client/libs/admin/statistik/src/index.ts b/alfa-client/libs/admin/statistik/src/index.ts
index 157271feb3..5b433fe321 100644
--- a/alfa-client/libs/admin/statistik/src/index.ts
+++ b/alfa-client/libs/admin/statistik/src/index.ts
@@ -1,2 +1,2 @@
 export * from './lib/statistik-container/statistik-container.component';
-export * from './lib/statistik-fields-form/admin-statistik-fields-form.component';
+export * from './lib/statistik-fields-form/statistik-fields-form.component';
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.html
deleted file mode 100644
index 569fc993f6..0000000000
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<form [formGroup]="formService.form">
-  <div class="flex flex-col gap-4" [formArrayName]="StatistikFieldsFormService.FIELD_MAPPINGS">
-    <div
-      *ngFor="let mappingControl of formService.mappings.controls; let i = index"
-      [formGroupName]="i"
-      class="flex w-full gap-2"
-    >
-      <ods-text-editor
-        class="flex-1"
-        formControlName="sourcePath"
-        label="Pfad des Datenfeldes"
-        placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
-        [dataTestId]="'mapping-field-' + i"
-        [attr.data-test-id]="'mapping-field-' + i"
-      ></ods-text-editor>
-      <ods-button
-        class="self-end"
-        variant="ghost"
-        size="fit"
-        destructive="true"
-        (clickEmitter)="formService.removeMapping(i)"
-        [dataTestId]="'remove-mapping-button-' + i"
-        [attr.data-test-id]="'remove-mapping-' + i"
-      >
-        <ods-delete-icon icon />
-      </ods-button>
-    </div>
-  </div>
-</form>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.ts
deleted file mode 100644
index 48bc3eaddd..0000000000
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { ADMIN_FORMSERVICE, AdminCancelButtonComponent, AdminSaveButtonComponent, ROUTES } from '@admin-client/shared';
-import { CommonModule } from '@angular/common';
-import { Component, inject } from '@angular/core';
-import { ReactiveFormsModule } from '@angular/forms';
-import { TextEditorComponent } from '@ods/component';
-import { ButtonComponent, DeleteIconComponent, PlusIconComponent } from '@ods/system';
-import { StatistikFieldsFormService } from '../statistik-fields.formservice';
-
-@Component({
-  selector: 'statistik-fields-form-mapping',
-  templateUrl: './statistik-fields-form-mapping.component.html',
-  standalone: true,
-  imports: [
-    CommonModule,
-    ButtonComponent,
-    PlusIconComponent,
-    ReactiveFormsModule,
-    TextEditorComponent,
-    DeleteIconComponent,
-    AdminSaveButtonComponent,
-    AdminCancelButtonComponent,
-  ],
-})
-export class AdminStatistikFieldsFormMappingComponent {
-  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
-
-  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
-  public readonly Routes = ROUTES;
-}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
similarity index 94%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.html
rename to alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
index ce24e7184c..ab0c86ae99 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
@@ -1,7 +1,7 @@
 <h2 class="heading-2" data-test-id="statistik-fields-form-header-text">Felder zur Auswertung hinzufügen</h2>
 
 <div class="flex max-w-4xl flex-col gap-4">
-  <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-4">
+  <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-2">
     <div [formGroupName]="StatistikFieldsFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
       <ods-text-editor
         [formControlName]="StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME"
@@ -18,7 +18,7 @@
         dataTestId="form-id"
       ></ods-text-editor>
     </div>
-    <statistik-fields-form-mapping />
+    <admin-statistik-fields-form-mapping />
   </form>
   <ods-button
     text="Datenfeld hinzufügen"
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
similarity index 84%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.spec.ts
rename to alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
index e124d07cf7..8a2c2cbe25 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
@@ -9,13 +9,13 @@ import { MockComponent } from 'ng-mocks';
 import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
 import { AdminCancelButtonComponent } from '../../../../shared/src/lib/admin-cancel-button/admin-cancel-button.component';
 import { AdminSaveButtonComponent } from '../../../../shared/src/lib/admin-save-button/admin-save-button.component';
-import { AdminStatistikFieldsFormComponent } from './admin-statistik-fields-form.component';
-import { AdminStatistikFieldsFormMappingComponent } from './statistik-fields-form-mapping/statistik-fields-form-mapping.component';
+import { StatistikFieldsFormComponent } from './statistik-fields-form.component';
+import { StatistikFieldsMappingsFormComponent } from './statistik-fields-mappings-form/statistik-fields-mappings-form.component';
 import { StatistikFieldsFormService } from './statistik-fields.formservice';
 
 describe('AdminStatistikFieldsFormComponent', () => {
-  let component: AdminStatistikFieldsFormComponent;
-  let fixture: ComponentFixture<AdminStatistikFieldsFormComponent>;
+  let component: StatistikFieldsFormComponent;
+  let fixture: ComponentFixture<StatistikFieldsFormComponent>;
 
   const formEngineNameInputTestId: string = getDataTestIdOf('form-engine-name');
   const formIdInputTestId: string = getDataTestIdOf('form-id');
@@ -36,18 +36,18 @@ describe('AdminStatistikFieldsFormComponent', () => {
     formService = <any>{ ...mock(StatistikFieldsFormService), form };
 
     await TestBed.configureTestingModule({
-      declarations: [
-        AdminStatistikFieldsFormComponent,
+      imports: [
+        ReactiveFormsModule,
+        StatistikFieldsFormComponent,
         MockComponent(TextEditorComponent),
         MockComponent(ButtonComponent),
         MockComponent(PlusIconComponent),
         MockComponent(AdminSaveButtonComponent),
         MockComponent(AdminCancelButtonComponent),
-        MockComponent(AdminStatistikFieldsFormMappingComponent),
+        MockComponent(StatistikFieldsMappingsFormComponent),
       ],
-      imports: [ReactiveFormsModule],
     })
-      .overrideComponent(AdminStatistikFieldsFormComponent, {
+      .overrideComponent(StatistikFieldsFormComponent, {
         set: {
           providers: [
             {
@@ -63,7 +63,7 @@ describe('AdminStatistikFieldsFormComponent', () => {
       })
       .compileComponents();
 
-    fixture = TestBed.createComponent(AdminStatistikFieldsFormComponent);
+    fixture = TestBed.createComponent(StatistikFieldsFormComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
similarity index 69%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.ts
rename to alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
index 0298196202..bd10b25953 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
@@ -2,27 +2,26 @@ import { ADMIN_FORMSERVICE, AdminCancelButtonComponent, AdminSaveButtonComponent
 import { Component, inject } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { TextEditorComponent } from '@ods/component';
-import { ButtonComponent, DeleteIconComponent, PlusIconComponent } from '@ods/system';
-import { AdminStatistikFieldsFormMappingComponent } from './statistik-fields-form-mapping/statistik-fields-form-mapping.component';
+import { ButtonComponent, PlusIconComponent } from '@ods/system';
+import { StatistikFieldsMappingsFormComponent } from './statistik-fields-mappings-form/statistik-fields-mappings-form.component';
 import { StatistikFieldsFormService } from './statistik-fields.formservice';
 
 @Component({
   selector: 'admin-statistik-fields-form',
-  templateUrl: './admin-statistik-fields-form.component.html',
+  templateUrl: './statistik-fields-form.component.html',
   standalone: true,
   imports: [
     ButtonComponent,
     PlusIconComponent,
     ReactiveFormsModule,
     TextEditorComponent,
-    DeleteIconComponent,
     AdminSaveButtonComponent,
     AdminCancelButtonComponent,
-    AdminStatistikFieldsFormMappingComponent,
+    StatistikFieldsMappingsFormComponent,
   ],
   providers: [{ provide: ADMIN_FORMSERVICE, useClass: StatistikFieldsFormService }],
 })
-export class AdminStatistikFieldsFormComponent {
+export class StatistikFieldsFormComponent {
   public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
 
   public readonly StatistikFieldsFormService = StatistikFieldsFormService;
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
new file mode 100644
index 0000000000..b7af910dbf
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
@@ -0,0 +1,38 @@
+<form [formGroup]="formService.form">
+  <ng-container [formArrayName]="StatistikFieldsFormService.FIELD_MAPPINGS">
+    <ng-container [formGroupName]="index">
+      <div class="flex w-full flex-col gap-2 mt-4 bg-gray-100 p-4 rounded-md">
+        <div class="flex flex-row items-center justify-between">
+          <p class="text-md mb-2 block font-medium text-text">Datenfeld</p>
+          <ods-button
+            class="self-end"
+            variant="ghost"
+            size="fit"
+            destructive="true"
+            (clickEmitter)="formService.removeMapping(index)"
+            [dataTestId]="'remove-mapping-button-' + index"
+            [attr.data-test-id]="'remove-mapping-' + index"
+          >
+            <ods-delete-icon icon />
+          </ods-button>
+        </div>
+        <ods-text-editor
+          class="flex-1"
+          formControlName="sourcePath"
+          label="Pfad *"
+          placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
+          [dataTestId]="'source-mapping-field-' + index"
+          [attr.data-test-id]="'source-mapping-field-' + index"
+        ></ods-text-editor>
+        <ods-text-editor
+          class="flex-1"
+          formControlName="targetPath"
+          label="Zielfeld *"
+          placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
+          [dataTestId]="'target-mapping-field-' + index"
+          [attr.data-test-id]="'target-mapping-field-' + index"
+        ></ods-text-editor>
+      </div>
+    </ng-container>
+  </ng-container>
+</form>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts
new file mode 100644
index 0000000000..ff1cd734ac
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts
@@ -0,0 +1,99 @@
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { EMPTY_STRING } from '@alfa-client/tech-shared';
+import { existsAsHtmlElement, mock, Mock, mockGetValue, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
+import { expect } from '@jest/globals';
+import { TextEditorComponent } from '@ods/component';
+import { ButtonComponent, DeleteIconComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { StatistikFieldsFormService } from '../../statistik-fields.formservice';
+import { StatistikFieldMappingFormComponent } from './statistik-field-mapping-form.component';
+
+describe('AdminStatistikFieldMappingFormComponent', () => {
+  let component: StatistikFieldMappingFormComponent;
+  let fixture: ComponentFixture<StatistikFieldMappingFormComponent>;
+
+  const formBuilder: FormBuilder = new FormBuilder();
+  const fieldIndex: number = 0;
+  const sourcePathEditorTestId: string = getDataTestIdOf('source-mapping-field-0');
+  const targetPathEditorTestId: string = getDataTestIdOf('target-mapping-field-0');
+  const removeMappingButtonTestId: string = getDataTestIdOf('remove-mapping-0');
+
+  let formService: Mock<StatistikFieldsFormService>;
+
+  beforeEach(async () => {
+    const form: FormGroup = formBuilder.group({
+      [StatistikFieldsFormService.FIELD_MAPPINGS]: formBuilder.array([
+        new FormGroup({
+          [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
+          [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+        }),
+      ]),
+    });
+
+    formService = <any>{
+      ...mock(StatistikFieldsFormService),
+      form,
+      addMapping: jest.fn(),
+      removeMapping: jest.fn(),
+    };
+
+    mockGetValue(
+      formService,
+      StatistikFieldsFormService.FIELD_MAPPINGS,
+      form.controls[StatistikFieldsFormService.FIELD_MAPPINGS],
+    );
+
+    await TestBed.configureTestingModule({
+      imports: [
+        StatistikFieldMappingFormComponent,
+        MockComponent(TextEditorComponent),
+        MockComponent(ButtonComponent),
+        MockComponent(DeleteIconComponent),
+      ],
+      providers: [
+        {
+          provide: ADMIN_FORMSERVICE,
+          useValue: formService,
+        },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(StatistikFieldMappingFormComponent);
+    component = fixture.componentInstance;
+    component.index = fieldIndex;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    describe('remove mapping button', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, removeMappingButtonTestId);
+      });
+
+      it('should remove mapping on click', () => {
+        triggerEvent({ fixture, elementSelector: removeMappingButtonTestId, name: 'clickEmitter', data: fieldIndex });
+
+        expect(formService.removeMapping).toHaveBeenCalledWith(fieldIndex);
+      });
+    });
+
+    describe('source path text editor', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, sourcePathEditorTestId);
+      });
+    });
+
+    describe('target path text editor', () => {
+      it('should should exists', () => {
+        existsAsHtmlElement(fixture, targetPathEditorTestId);
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts
new file mode 100644
index 0000000000..0789e17703
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts
@@ -0,0 +1,20 @@
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { Component, inject, Input } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { TextEditorComponent } from '@ods/component';
+import { ButtonComponent, DeleteIconComponent } from '@ods/system';
+import { StatistikFieldsFormService } from '../../statistik-fields.formservice';
+
+@Component({
+  selector: 'admin-statistik-field-mapping-form',
+  standalone: true,
+  templateUrl: './statistik-field-mapping-form.component.html',
+  imports: [ButtonComponent, DeleteIconComponent, ReactiveFormsModule, TextEditorComponent],
+})
+export class StatistikFieldMappingFormComponent {
+  @Input({ required: true }) index: number;
+
+  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
+
+  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html
new file mode 100644
index 0000000000..7e2804257f
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html
@@ -0,0 +1,10 @@
+<form [formGroup]="formService.form">
+  <div class="flex flex-col" [formArrayName]="StatistikFieldsFormService.FIELD_MAPPINGS">
+    <div *ngFor="let ignore of mappingsFormArray; let i = index">
+      <admin-statistik-field-mapping-form
+        [index]="i"
+        [attr.data-test-id]="'statistik-field-mapping-form-' + i"
+      ></admin-statistik-field-mapping-form>
+    </div>
+  </div>
+</form>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts
similarity index 51%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.spec.ts
rename to alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts
index d06746e48f..6470d91cfe 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts
@@ -1,21 +1,20 @@
 import { ADMIN_FORMSERVICE } from '@admin-client/shared';
 import { EMPTY_STRING } from '@alfa-client/tech-shared';
-import { dispatchEventFromFixture, existsAsHtmlElement, mock, Mock, MockEvent, mockGetValue } from '@alfa-client/test-utils';
+import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock, mockGetValue } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
-import { TextEditorComponent } from '@ods/component';
-import { ButtonComponent, DeleteIconComponent } from '@ods/system';
+import { expect } from '@jest/globals';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { StatistikFieldsFormService } from '../statistik-fields.formservice';
-import { AdminStatistikFieldsFormMappingComponent } from './statistik-fields-form-mapping.component';
+import { StatistikFieldMappingFormComponent } from './statistik-field-mapping-form/statistik-field-mapping-form.component';
+import { StatistikFieldsMappingsFormComponent } from './statistik-fields-mappings-form.component';
 
-describe('AdminStatistikFieldsFormMappingComponent', () => {
-  let component: AdminStatistikFieldsFormMappingComponent;
-  let fixture: ComponentFixture<AdminStatistikFieldsFormMappingComponent>;
+describe('StatistikFieldsFormMappingComponent', () => {
+  let component: StatistikFieldsMappingsFormComponent;
+  let fixture: ComponentFixture<StatistikFieldsMappingsFormComponent>;
 
-  const mappingField: string = getDataTestIdOf('mapping-field-0');
-  const removeMappingButton: string = getDataTestIdOf('remove-mapping-0');
+  const mappingForm: string = getDataTestIdOf('statistik-field-mapping-form-0');
 
   const formBuilder: FormBuilder = new FormBuilder();
 
@@ -24,7 +23,10 @@ describe('AdminStatistikFieldsFormMappingComponent', () => {
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
       [StatistikFieldsFormService.FIELD_MAPPINGS]: formBuilder.array([
-        new FormGroup({ sourcePath: new FormControl(EMPTY_STRING) }),
+        new FormGroup({
+          [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
+          [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+        }),
       ]),
     });
 
@@ -42,18 +44,8 @@ describe('AdminStatistikFieldsFormMappingComponent', () => {
     );
 
     await TestBed.configureTestingModule({
-      declarations: [
-        AdminStatistikFieldsFormMappingComponent,
-        MockComponent(TextEditorComponent),
-        MockComponent(ButtonComponent),
-        MockComponent(DeleteIconComponent),
-      ],
-      imports: [ReactiveFormsModule],
+      imports: [ReactiveFormsModule, StatistikFieldsMappingsFormComponent, MockComponent(StatistikFieldMappingFormComponent)],
       providers: [
-        {
-          provide: StatistikFieldsFormService,
-          useValue: formService,
-        },
         {
           provide: ADMIN_FORMSERVICE,
           useValue: formService,
@@ -61,7 +53,7 @@ describe('AdminStatistikFieldsFormMappingComponent', () => {
       ],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(AdminStatistikFieldsFormMappingComponent);
+    fixture = TestBed.createComponent(StatistikFieldsMappingsFormComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
@@ -75,15 +67,13 @@ describe('AdminStatistikFieldsFormMappingComponent', () => {
       it('should exists', () => {
         fixture.detectChanges();
 
-        existsAsHtmlElement(fixture, mappingField);
+        existsAsHtmlElement(fixture, mappingForm);
       });
-    });
 
-    describe('remove mapping button', () => {
-      it('should call formservice', () => {
-        dispatchEventFromFixture(fixture, removeMappingButton, MockEvent.CLICK);
+      it('should have inputs', () => {
+        const mappingComponent: StatistikFieldMappingFormComponent = getElementComponentFromFixtureByCss(fixture, mappingForm);
 
-        expect(formService.removeMapping).toHaveBeenCalledWith(0);
+        expect(mappingComponent.index).toEqual(0);
       });
     });
   });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts
new file mode 100644
index 0000000000..ff8b9135d1
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts
@@ -0,0 +1,20 @@
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { CommonModule } from '@angular/common';
+import { Component, inject } from '@angular/core';
+import { AbstractControl, ReactiveFormsModule } from '@angular/forms';
+import { StatistikFieldsFormService } from '../statistik-fields.formservice';
+import { StatistikFieldMappingFormComponent } from './statistik-field-mapping-form/statistik-field-mapping-form.component';
+
+@Component({
+  selector: 'admin-statistik-fields-form-mapping',
+  templateUrl: './statistik-fields-mappings-form.component.html',
+  standalone: true,
+  imports: [CommonModule, ReactiveFormsModule, StatistikFieldMappingFormComponent],
+})
+export class StatistikFieldsMappingsFormComponent {
+  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
+
+  public readonly mappingsFormArray: AbstractControl[] = this.formService.mappings.controls;
+
+  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
index 58a2273cb6..2bb935d50e 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { AggregationMappingResource, AggregationMappingService } from '@admin-client/reporting-shared';
-import { EMPTY_STRING, StateResource, createStateResource } from '@alfa-client/tech-shared';
+import { createStateResource, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
 import { FormArray, FormControl, FormGroup } from '@angular/forms';
@@ -71,21 +71,30 @@ describe('StatistikFieldsFormService', () => {
 
       const mappingFormArray: FormArray = <FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS];
       expect(mappingFormArray).toHaveLength(2);
-      expect(mappingFormArray.controls[0].value).toEqual({ sourcePath: EMPTY_STRING });
+      expect(mappingFormArray.controls[0].value).toEqual({
+        [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+      });
     });
   });
 
   describe('remove mapping', () => {
     it('should remove mapping control', () => {
       (<FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS]).push(
-        new FormGroup({ sourcePath: new FormControl('controlToRemove') }),
+        new FormGroup({
+          [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl('controlToRemove'),
+          [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl('controlToRemove'),
+        }),
       );
 
       formService.removeMapping(1);
 
       const mappingFormArray: FormArray = <FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS];
       expect(mappingFormArray).toHaveLength(1);
-      expect(mappingFormArray.controls[0].value).toEqual({ sourcePath: EMPTY_STRING });
+      expect(mappingFormArray.controls[0].value).toEqual({
+        [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+      });
     });
   });
 
@@ -94,7 +103,10 @@ describe('StatistikFieldsFormService', () => {
       const mappings: FormArray = formService.mappings;
 
       expect(mappings).toHaveLength(1);
-      expect(mappings.controls[0].value).toEqual({ sourcePath: EMPTY_STRING });
+      expect(mappings.controls[0].value).toEqual({
+        [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+      });
     });
   });
 });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
index 1b746e12f4..54ffc761c9 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
@@ -13,6 +13,8 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
   public static readonly FIELD_FORM_ID: string = 'formId';
 
   public static readonly FIELD_MAPPINGS: string = 'mappings';
+  public static readonly FIELD_MAPPING_SOURCE_PATH = 'sourcePath';
+  public static readonly FIELD_MAPPING_TARGET_PATH = 'targetPath';
 
   protected initForm(): UntypedFormGroup {
     return this.formBuilder.group({
@@ -37,7 +39,10 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
   }
 
   private createArrayControl(): FormGroup {
-    return new FormGroup({ sourcePath: new FormControl(EMPTY_STRING) });
+    return new FormGroup({
+      [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
+      [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+    });
   }
 
   public removeMapping(index: number): void {
-- 
GitLab


From 3d1899627b0de9aa5b604b5d6c32cb99aa95af93 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 11 Mar 2025 07:24:52 +0100
Subject: [PATCH 02/47] OZG-7473 add name field

Sub task: OZG-7882
---
 .../statistik-fields-form.component.html              | 11 +++++++++--
 .../statistik-fields.formservice.ts                   |  7 ++++---
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
index ab0c86ae99..a2922837c1 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
@@ -2,17 +2,24 @@
 
 <div class="flex max-w-4xl flex-col gap-4">
   <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-2">
+    <ods-text-editor
+      [formControlName]="StatistikFieldsFormService.FIELD_NAME"
+      label="Name *"
+      placeholder=""
+      data-test-id="statistik-name-text-editor"
+      dataTestId="statistik-name"
+    ></ods-text-editor>
     <div [formGroupName]="StatistikFieldsFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
       <ods-text-editor
         [formControlName]="StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME"
-        label="Formengine"
+        label="Formengine *"
         placeholder="Tragen Sie hier die Formengine des Formulars ein."
         data-test-id="form-engine-name"
         dataTestId="form-engine-name"
       ></ods-text-editor>
       <ods-text-editor
         [formControlName]="StatistikFieldsFormService.FIELD_FORM_ID"
-        label="FormID"
+        label="FormID *"
         placeholder="Tragen Sie hier die FormID des Formulars ein."
         data-test-id="form-id"
         dataTestId="form-id"
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
index 54ffc761c9..67ecb47a0b 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
@@ -6,18 +6,19 @@ import { Observable } from 'rxjs';
 
 @Injectable()
 export class StatistikFieldsFormService extends AbstractFormService<AggregationMappingResource> {
-  private service = inject(AggregationMappingService);
-
+  public static readonly FIELD_NAME: string = 'name';
   public static readonly FIELD_FORM_IDENTIFIER: string = 'formIdentifier';
   public static readonly FIELD_FORM_ENGINE_NAME: string = 'formEngineName';
   public static readonly FIELD_FORM_ID: string = 'formId';
-
   public static readonly FIELD_MAPPINGS: string = 'mappings';
   public static readonly FIELD_MAPPING_SOURCE_PATH = 'sourcePath';
   public static readonly FIELD_MAPPING_TARGET_PATH = 'targetPath';
 
+  private service = inject(AggregationMappingService);
+
   protected initForm(): UntypedFormGroup {
     return this.formBuilder.group({
+      [StatistikFieldsFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
       [StatistikFieldsFormService.FIELD_FORM_IDENTIFIER]: this.formBuilder.group({
         [StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
         [StatistikFieldsFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
-- 
GitLab


From a389485ead9d547ed268766073833188fa6d3d1a Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 11 Mar 2025 07:48:37 +0100
Subject: [PATCH 03/47] OZG-7473 add aggregation mapping name

Sub task: OZG-7882
---
 .../admin/reporting-shared/src/lib/aggregation-mapping.model.ts | 2 ++
 .../libs/admin/reporting-shared/test/aggregation-mapping.ts     | 1 +
 2 files changed, 3 insertions(+)

diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.model.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.model.ts
index 0db6cb4e39..5d1e7e3fee 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.model.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.model.ts
@@ -2,6 +2,7 @@ import { ListResource } from '@alfa-client/tech-shared';
 import { Resource } from '@ngxp/rest';
 
 export interface AggregationMapping {
+  name: string;
   formIdentifier: FormIdentifier;
   mappings: FieldMapping[];
 }
@@ -17,4 +18,5 @@ export interface FieldMapping {
 }
 
 export interface AggregationMappingResource extends AggregationMapping, Resource {}
+
 export interface AggregationMappingListResource extends ListResource {}
diff --git a/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts b/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
index acbcc9fa75..e71b646a80 100644
--- a/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
+++ b/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
@@ -7,6 +7,7 @@ import { AggregationMappingListLinkRel } from '../src/lib/aggregation-mapping.li
 
 export function createAggregationMapping(): AggregationMapping {
   return {
+    name: faker.word.noun(),
     formIdentifier: {
       formEngineName: faker.lorem.word(),
       formId: faker.string.uuid(),
-- 
GitLab


From 15c18f89ef3c95cf3662cc563afb8baf087c0d03 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 11 Mar 2025 07:51:19 +0100
Subject: [PATCH 04/47] OZG-7473 fix unit test

Sub task: OZG-7882
---
 .../statistik-fields-form.component.spec.ts                      | 1 +
 1 file changed, 1 insertion(+)

diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
index 8a2c2cbe25..fc823f9d6c 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
@@ -27,6 +27,7 @@ describe('AdminStatistikFieldsFormComponent', () => {
 
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
+      [StatistikFieldsFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
       [StatistikFieldsFormService.FIELD_FORM_IDENTIFIER]: formBuilder.group({
         [StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
         [StatistikFieldsFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
-- 
GitLab


From 6f730e42dd49751388734b71d3786e548ef5475b Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 11 Mar 2025 15:05:34 +0100
Subject: [PATCH 05/47] OZG-7473 add list component

Sub task: OZG-7883
---
 ...gregation-mapping-list-item.component.html |  10 ++
 ...gation-mapping-list-item.component.spec.ts |  21 +++
 ...aggregation-mapping-list-item.component.ts |  14 ++
 .../aggregation-mapping-list.component.html   |   7 +
 ...aggregation-mapping-list.component.spec.ts | 120 ++++++++++++++++++
 .../aggregation-mapping-list.component.ts     |  31 +++++
 .../statistik-container.component.html        |   2 +-
 .../statistik-container.component.spec.ts     |  32 ++++-
 .../statistik-container.component.ts          |   3 +-
 alfa-client/libs/test-utils/src/lib/helper.ts |   4 +-
 .../libs/test-utils/src/lib/jest.helper.ts    |  11 +-
 11 files changed, 247 insertions(+), 8 deletions(-)
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.ts

diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
new file mode 100644
index 0000000000..8bf3593a46
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -0,0 +1,10 @@
+<ods-list-item [path]="" [attr.data-test-id]="(aggregationMapping.name | convertForDataTest)">
+  <div class="flex-1 basis-1/2">
+    <div class="mb-2 flex flex-wrap items-center gap-3">
+      <h3 class="text-md font-semibold" data-test-class="fullname">{{ aggregationMapping.name }}</h3>
+    </div>
+    <!-- Remove null safe check operator after backend provides correct data. -->
+    <div>{{aggregationMapping.formIdentifier?.formEngineName}}</div>
+    <div>{{aggregationMapping.formIdentifier?.formId}}</div>
+  </div>
+</ods-list-item>
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
new file mode 100644
index 0000000000..7e48ac908d
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item.component';
+
+describe('AggregationMappingListItemComponent', () => {
+  let component: AggregationMappingListItemComponent;
+  let fixture: ComponentFixture<AggregationMappingListItemComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [AggregationMappingListItemComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AggregationMappingListItemComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
new file mode 100644
index 0000000000..ca31dbc05b
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
@@ -0,0 +1,14 @@
+import { AggregationMappingResource } from '@admin-client/reporting-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
+import { ListItemComponent } from '@ods/system';
+
+@Component({
+  selector: 'admin-aggregation-mapping-list-item',
+  standalone: true,
+  templateUrl: './aggregation-mapping-list-item.component.html',
+  imports: [ConvertForDataTestPipe, ListItemComponent],
+})
+export class AggregationMappingListItemComponent {
+  @Input({ required: true }) aggregationMapping: AggregationMappingResource;
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html
new file mode 100644
index 0000000000..2746dbebda
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html
@@ -0,0 +1,7 @@
+<ods-spinner [stateResource]="listStateResource">
+  <ods-list data-test-id="aggregation-mapping-list">
+    @for (aggregationMapping of aggregationMappings; track $index) {
+      <admin-aggregation-mapping-list-item [aggregationMapping]="aggregationMapping" />
+    }
+  </ods-list>
+</ods-spinner>
\ No newline at end of file
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
new file mode 100644
index 0000000000..dd1647f73a
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
@@ -0,0 +1,120 @@
+import { AggregationMappingListResource } from '@admin-client/reporting-shared';
+import {
+  createEmptyStateResource,
+  createLoadingStateResource,
+  createStateResource,
+  getEmbeddedResources,
+  StateResource,
+} from '@alfa-client/tech-shared';
+import { expectComponentExistsInTemplate, getElementFromFixtureByType } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
+import { SpinnerComponent } from '@ods/component';
+import { ListComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { AggregationMappingListLinkRel } from '../../../../reporting-shared/src/lib/aggregation-mapping.linkrel';
+import { createAggregationMappingListResource } from '../../../../reporting-shared/test/aggregation-mapping';
+import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item/aggregation-mapping-list-item.component';
+import { AggregationMappingListComponent } from './aggregation-mapping-list.component';
+
+describe('AggregationMappingListComponent', () => {
+  let component: AggregationMappingListComponent;
+  let fixture: ComponentFixture<AggregationMappingListComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [
+        AggregationMappingListComponent,
+        MockComponent(SpinnerComponent),
+        MockComponent(ListComponent),
+        MockComponent(AggregationMappingListItemComponent),
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AggregationMappingListComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('component', () => {
+    const aggregationMappingListStateResource: StateResource<AggregationMappingListResource> = createStateResource(
+      createAggregationMappingListResource(),
+    );
+
+    it('should have initial state', () => {
+      expect(component.listStateResource).toEqual(createEmptyStateResource());
+      expect(component.aggregationMappings).toEqual([]);
+    });
+
+    describe('_update', () => {
+      it('should set list state resource', () => {
+        component.aggregationMappingListStateResource = aggregationMappingListStateResource;
+
+        expect(component.listStateResource).toEqual(aggregationMappingListStateResource);
+      });
+
+      it('should set aggregation mappings if loaded and not nil', () => {
+        component.aggregationMappingListStateResource = aggregationMappingListStateResource;
+
+        expect(component.aggregationMappings).toEqual(
+          getEmbeddedResources(aggregationMappingListStateResource, AggregationMappingListLinkRel.LIST),
+        );
+      });
+
+      it('should NOT set aggregation mappings if nil', () => {
+        component.aggregationMappingListStateResource = null;
+
+        expect(component.aggregationMappings).toEqual([]);
+      });
+
+      it('should NOT set aggregation mappings if loading', () => {
+        component.aggregationMappingListStateResource = createLoadingStateResource();
+
+        expect(component.aggregationMappings).toEqual([]);
+      });
+    });
+
+    describe('set aggregation mapping list state resource', () => {
+      it('should update component state', () => {
+        component._update = jest.fn();
+
+        component.aggregationMappingListStateResource = aggregationMappingListStateResource;
+
+        expect(component._update).toHaveBeenCalledWith(aggregationMappingListStateResource);
+      });
+    });
+  });
+
+  describe('template', () => {
+    const aggregationMappingListStateResource: StateResource<AggregationMappingListResource> = createStateResource(
+      createAggregationMappingListResource(),
+    );
+
+    beforeEach(() => {
+      component.aggregationMappingListStateResource = aggregationMappingListStateResource;
+      fixture.detectChanges();
+    });
+
+    it('should have spinner with state resource', () => {
+      expectComponentExistsInTemplate(fixture, SpinnerComponent);
+      const comp = getElementFromFixtureByType(fixture, SpinnerComponent);
+      expect(comp.stateResource).toEqual(aggregationMappingListStateResource);
+    });
+
+    it('should have list', () => {
+      expectComponentExistsInTemplate(fixture, ListComponent);
+    });
+
+    it('should have list item with mapping', () => {
+      expectComponentExistsInTemplate(fixture, AggregationMappingListItemComponent);
+      const comp = getElementFromFixtureByType(fixture, AggregationMappingListItemComponent);
+      expect(comp.aggregationMapping).toEqual(
+        getEmbeddedResources(aggregationMappingListStateResource, AggregationMappingListLinkRel.LIST)[0],
+      );
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.ts
new file mode 100644
index 0000000000..c427bc7903
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.ts
@@ -0,0 +1,31 @@
+import { AggregationMappingListResource, AggregationMappingResource } from '@admin-client/reporting-shared';
+import { createEmptyStateResource, getEmbeddedResources, isLoaded, isNotNil, StateResource } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
+import { SpinnerComponent } from '@ods/component';
+import { ListComponent } from '@ods/system';
+import { AggregationMappingListLinkRel } from '../../../../reporting-shared/src/lib/aggregation-mapping.linkrel';
+import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item/aggregation-mapping-list-item.component';
+
+@Component({
+  selector: 'admin-aggregation-mapping-list',
+  standalone: true,
+  templateUrl: './aggregation-mapping-list.component.html',
+  imports: [SpinnerComponent, ListComponent, AggregationMappingListItemComponent],
+})
+export class AggregationMappingListComponent {
+  @Input({ required: true }) set aggregationMappingListStateResource(
+    stateResource: StateResource<AggregationMappingListResource>,
+  ) {
+    this._update(stateResource);
+  }
+
+  public listStateResource: StateResource<AggregationMappingListResource> = createEmptyStateResource();
+  public aggregationMappings: AggregationMappingResource[] = [];
+
+  _update(stateResource: StateResource<AggregationMappingListResource>): void {
+    this.listStateResource = stateResource;
+    if (isNotNil(stateResource) && isLoaded(stateResource)) {
+      this.aggregationMappings = getEmbeddedResources(stateResource, AggregationMappingListLinkRel.LIST);
+    }
+  }
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
index 1fd0441a39..f7cb1c606f 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
@@ -32,4 +32,4 @@
   ></ods-routing-button>
 </div>
 
-<ng-container *ngIf="listStateResource$ | async"></ng-container>
+<admin-aggregation-mapping-list [aggregationMappingListStateResource]="listStateResource$ | async"></admin-aggregation-mapping-list>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
index 3abca44e4a..014109b6a8 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
@@ -23,12 +23,15 @@
  */
 import { AggregationMappingListResource, AggregationMappingService } from '@admin-client/reporting-shared';
 import { createStateResource, StateResource } from '@alfa-client/tech-shared';
-import { mock, Mock } from '@alfa-client/test-utils';
+import { expectComponentExistsInTemplate, getElementFromFixtureByType, mock, Mock } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
 import { RoutingButtonComponent } from '@ods/component';
 import { singleCold } from 'libs/tech-shared/test/marbles';
 import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
 import { createAggregationMappingListResource } from '../../../../reporting-shared/test/aggregation-mapping';
+import { AggregationMappingListComponent } from '../aggregation-mapping-list/aggregation-mapping-list.component';
 import { StatistikContainerComponent } from './statistik-container.component';
 
 describe('StatistikContainerComponent', () => {
@@ -41,8 +44,11 @@ describe('StatistikContainerComponent', () => {
     aggregationMappingService = mock(AggregationMappingService);
 
     await TestBed.configureTestingModule({
-      imports: [StatistikContainerComponent],
-      declarations: [MockComponent(RoutingButtonComponent)],
+      imports: [
+        StatistikContainerComponent,
+        MockComponent(RoutingButtonComponent),
+        MockComponent(AggregationMappingListComponent),
+      ],
     })
       .overrideComponent(StatistikContainerComponent, {
         set: {
@@ -86,4 +92,24 @@ describe('StatistikContainerComponent', () => {
       expect(component.listStateResource$).toBeObservable(singleCold(stateResource));
     });
   });
+
+  describe('template', () => {
+    describe('aggregation mapping list', () => {
+      it('should exists', () => {
+        expectComponentExistsInTemplate(fixture, AggregationMappingListComponent);
+      });
+
+      it('should have inputs', () => {
+        const stateResource: StateResource<AggregationMappingListResource> = createStateResource(
+          createAggregationMappingListResource(),
+        );
+        component.listStateResource$ = of(stateResource);
+        fixture.detectChanges();
+
+        const comp = getElementFromFixtureByType(fixture, AggregationMappingListComponent);
+
+        expect(comp.aggregationMappingListStateResource).toEqual(stateResource);
+      });
+    });
+  });
 });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
index 90c3515896..70db01b592 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
@@ -28,12 +28,13 @@ import { CommonModule } from '@angular/common';
 import { Component, inject, OnInit } from '@angular/core';
 import { RoutingButtonComponent } from '@ods/component';
 import { Observable } from 'rxjs';
+import { AggregationMappingListComponent } from '../aggregation-mapping-list/aggregation-mapping-list.component';
 
 @Component({
   selector: 'admin-statistik-container',
   templateUrl: './statistik-container.component.html',
   standalone: true,
-  imports: [CommonModule, RoutingButtonComponent],
+  imports: [CommonModule, RoutingButtonComponent, AggregationMappingListComponent],
   providers: [AggregationMappingService],
 })
 export class StatistikContainerComponent implements OnInit {
diff --git a/alfa-client/libs/test-utils/src/lib/helper.ts b/alfa-client/libs/test-utils/src/lib/helper.ts
index 66f33c3579..df9518764f 100644
--- a/alfa-client/libs/test-utils/src/lib/helper.ts
+++ b/alfa-client/libs/test-utils/src/lib/helper.ts
@@ -26,8 +26,8 @@ import { ComponentFixture } from '@angular/core/testing';
 import { By } from '@angular/platform-browser';
 import { EventData } from './model';
 
-export function getElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): T {
-  return getDebugElementFromFixtureByType(fixture, component).componentInstance as T;
+export function getElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): T | null {
+  return getDebugElementFromFixtureByType(fixture, component)?.componentInstance as T;
 }
 
 function getDebugElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): DebugElement {
diff --git a/alfa-client/libs/test-utils/src/lib/jest.helper.ts b/alfa-client/libs/test-utils/src/lib/jest.helper.ts
index 60df8592af..1b0f86ec5b 100644
--- a/alfa-client/libs/test-utils/src/lib/jest.helper.ts
+++ b/alfa-client/libs/test-utils/src/lib/jest.helper.ts
@@ -21,10 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { Type } from '@angular/core';
 import { ComponentFixture } from '@angular/core/testing';
 import { expect } from '@jest/globals';
 import { TooltipDirective } from '@ods/system';
-import { getDebugElementFromFixtureByCss, getElementFromFixture } from './helper';
+import { getDebugElementFromFixtureByCss, getElementFromFixture, getElementFromFixtureByType } from './helper';
 
 export function notExistsAsHtmlElement(fixture: ComponentFixture<any>, domElement: string): void {
   expect(getElementFromFixture(fixture, domElement)).not.toBeInstanceOf(HTMLElement);
@@ -34,6 +35,14 @@ export function existsAsHtmlElement(fixture: ComponentFixture<any>, domElement:
   expect(getElementFromFixture(fixture, domElement)).toBeInstanceOf(HTMLElement);
 }
 
+export function expectComponentExistsInTemplate<T>(fixture: ComponentFixture<any>, component: Type<T>): void {
+  expect(getElementFromFixtureByType(fixture, component)).toBeInstanceOf(component);
+}
+
+export function expectComponentMissingInTemplate<T>(fixture: ComponentFixture<any>, component: Type<T>): void {
+  expect(getElementFromFixtureByType(fixture, component)).toBeUndefined();
+}
+
 export function tooltipExistsWithText(fixture: ComponentFixture<any>, domElement: string, tooltipText: string) {
   const tooltipInstance = getDebugElementFromFixtureByCss(fixture, domElement).injector.get(TooltipDirective);
   expect(tooltipInstance.componentRef.instance.text).toBe(tooltipText);
-- 
GitLab


From 8c865aa0f98433991d0f41dff75f05c3f463a9b0 Mon Sep 17 00:00:00 2001
From: Alexander Reifschneider <alexander.reifschneider@mgm-tp.com>
Date: Tue, 11 Mar 2025 16:09:16 +0100
Subject: [PATCH 06/47] OZG-7473 Add initial list styling Sub-Task: OZG-7886

---
 .../aggregation-mapping-list-item.component.html  |  6 +++---
 .../aggregation-mapping-list-item.component.ts    |  1 +
 .../aggregation-mapping-list.component.html       |  2 +-
 .../statistik-container.component.html            | 15 +++++++--------
 .../design-system/src/lib/list/list.component.ts  |  3 +--
 5 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
index 8bf3593a46..426085047e 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -1,10 +1,10 @@
-<ods-list-item [path]="" [attr.data-test-id]="(aggregationMapping.name | convertForDataTest)">
+<ods-list-item [path]="" [attr.data-test-id]="aggregationMapping.name | convertForDataTest">
   <div class="flex-1 basis-1/2">
     <div class="mb-2 flex flex-wrap items-center gap-3">
       <h3 class="text-md font-semibold" data-test-class="fullname">{{ aggregationMapping.name }}</h3>
     </div>
     <!-- Remove null safe check operator after backend provides correct data. -->
-    <div>{{aggregationMapping.formIdentifier?.formEngineName}}</div>
-    <div>{{aggregationMapping.formIdentifier?.formId}}</div>
+    <p>{{ aggregationMapping.formIdentifier?.formEngineName }}</p>
+    <p>{{ aggregationMapping.formIdentifier?.formId }}</p>
   </div>
 </ods-list-item>
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
index ca31dbc05b..c022babf73 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
@@ -8,6 +8,7 @@ import { ListItemComponent } from '@ods/system';
   standalone: true,
   templateUrl: './aggregation-mapping-list-item.component.html',
   imports: [ConvertForDataTestPipe, ListItemComponent],
+  styles: [':host {@apply block}'],
 })
 export class AggregationMappingListItemComponent {
   @Input({ required: true }) aggregationMapping: AggregationMappingResource;
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html
index 2746dbebda..521fc9e92d 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html
@@ -4,4 +4,4 @@
       <admin-aggregation-mapping-list-item [aggregationMapping]="aggregationMapping" />
     }
   </ods-list>
-</ods-spinner>
\ No newline at end of file
+</ods-spinner>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
index f7cb1c606f..bd98c2aaea 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
@@ -24,12 +24,11 @@
 
 -->
 <h1 class="heading-1" data-test-id="statistik-header-text">Statistik</h1>
-<div class="mt-4 w-fit">
-  <ods-routing-button
-    [linkPath]="ROUTES.STATISTIK_NEU"
-    text="Weitere Felder auswerten"
-    dataTestId="weitere-felder-auswerten-button"
-  ></ods-routing-button>
-</div>
+<ods-routing-button
+  class="my-4 w-fit"
+  [linkPath]="ROUTES.STATISTIK_NEU"
+  text="Weitere Felder auswerten"
+  dataTestId="weitere-felder-auswerten-button"
+/>
 
-<admin-aggregation-mapping-list [aggregationMappingListStateResource]="listStateResource$ | async"></admin-aggregation-mapping-list>
+<admin-aggregation-mapping-list [aggregationMappingListStateResource]="listStateResource$ | async" />
diff --git a/alfa-client/libs/design-system/src/lib/list/list.component.ts b/alfa-client/libs/design-system/src/lib/list/list.component.ts
index 95c4bd3e72..3621cbb31f 100644
--- a/alfa-client/libs/design-system/src/lib/list/list.component.ts
+++ b/alfa-client/libs/design-system/src/lib/list/list.component.ts
@@ -23,12 +23,11 @@
  */
 import { CommonModule } from '@angular/common';
 import { Component } from '@angular/core';
-import { ListItemComponent } from './list-item/list-item.component';
 
 @Component({
   selector: 'ods-list',
   standalone: true,
-  imports: [CommonModule, ListItemComponent],
+  imports: [CommonModule],
   template: `
     <ul class="divide-y divide-gray-300 rounded-md bg-background-50 text-text shadow-sm ring-1 ring-gray-300 empty:hidden">
       <ng-content />
-- 
GitLab


From c9cdbdd92ab962269351a29c40ad8bf0f9fab4a1 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 11 Mar 2025 16:55:35 +0100
Subject: [PATCH 07/47] OZG-7473 navigate to list after save

Sub task: OZG-7884
---
 .../lib/aggregation-mapping.service.spec.ts   | 13 +++++-
 .../src/lib/aggregation-mapping.service.ts    |  6 ++-
 .../admin-save-button.component.spec.ts       | 46 +++++++++++++++++--
 .../admin-save-button.component.ts            | 20 ++++++--
 .../statistik-container.component.spec.ts     |  8 ++++
 .../statistik-container.component.ts          |  8 +++-
 .../statistik-fields-form.component.html      |  2 +-
 7 files changed, 88 insertions(+), 15 deletions(-)

diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
index ecf4387cee..d00e6923b0 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
@@ -1,6 +1,7 @@
-import { StateResource, createStateResource } from '@alfa-client/tech-shared';
+import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
 import { singleCold } from 'libs/tech-shared/test/marbles';
 import { Observable } from 'rxjs';
 import {
@@ -76,4 +77,14 @@ describe('AggregationMappingService', () => {
       expect(loadedAggregationMappingResource).toBeObservable(singleCold(aggregationMappingStateResource));
     });
   });
+
+  describe('refresh list', () => {
+    it('should call list resource service', () => {
+      listResourceService.refresh = jest.fn();
+
+      service.refreshList();
+
+      expect(listResourceService.refresh).toHaveBeenCalled();
+    });
+  });
 });
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
index 20a8ce6c1c..00402e238c 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
@@ -1,5 +1,5 @@
 import { StateResource } from '@alfa-client/tech-shared';
-import { Injectable, inject } from '@angular/core';
+import { inject, Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
 import { AggregationMappingListResourceService } from './aggregation-mapping-resource.service';
 import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
@@ -15,4 +15,8 @@ export class AggregationMappingService {
   public create(toCreate: AggregationMapping): Observable<StateResource<AggregationMappingResource>> {
     return this.listService.create(toCreate);
   }
+
+  public refreshList(): void {
+    this.listService.refresh();
+  }
 }
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
index baee873bfd..1d3a06aa4f 100644
--- a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
+++ b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
@@ -1,20 +1,32 @@
 import { ADMIN_FORMSERVICE } from '@admin-client/shared';
-import { AbstractFormService, createStateResource, StateResource } from '@alfa-client/tech-shared';
-import { dispatchEventFromFixture, getMockComponent, Mock, MockEvent } from '@alfa-client/test-utils';
+import { NavigationService } from '@alfa-client/navigation-shared';
+import { AbstractFormService, createStateResource, isValidStateResource, StateResource } from '@alfa-client/tech-shared';
+import { dispatchEventFromFixture, getMockComponent, mock, Mock, MockEvent } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { faker } from '@faker-js/faker/.';
+import { expect } from '@jest/globals';
 import { Resource } from '@ngxp/rest';
 import { ButtonWithSpinnerComponent } from '@ods/component';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { singleCold } from 'libs/tech-shared/test/marbles';
+import { singleColdCompleted } from 'libs/tech-shared/test/marbles';
 import { createDummyResource } from 'libs/tech-shared/test/resource';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
 import { AdminSaveButtonComponent } from './admin-save-button.component';
 
+jest.mock('@alfa-client/tech-shared', () => {
+  return {
+    ...jest.requireActual('@alfa-client/tech-shared'),
+    isValidStateResource: jest.fn(),
+  };
+});
+const isValidStateResourceMock: jest.Mock = isValidStateResource as jest.Mock;
+
 describe('AdminSaveButtonComponent', () => {
   let component: AdminSaveButtonComponent;
   let fixture: ComponentFixture<AdminSaveButtonComponent>;
 
+  let navigationService: Mock<NavigationService>;
   let formService: Mock<AbstractFormService<Resource>>;
 
   const saveButton: string = getDataTestIdOf('save');
@@ -22,7 +34,8 @@ describe('AdminSaveButtonComponent', () => {
   const stateResource: StateResource<Resource> = createStateResource(createDummyResource());
 
   beforeEach(async () => {
-    formService = <any>{ submit: jest.fn().mockReturnValue(singleCold(stateResource)) };
+    formService = <any>{ submit: jest.fn().mockReturnValue(of(stateResource)) };
+    navigationService = mock(NavigationService);
 
     await TestBed.configureTestingModule({
       imports: [AdminSaveButtonComponent],
@@ -32,6 +45,10 @@ describe('AdminSaveButtonComponent', () => {
           provide: ADMIN_FORMSERVICE,
           useValue: formService,
         },
+        {
+          provide: NavigationService,
+          useValue: navigationService,
+        },
       ],
     }).compileComponents();
 
@@ -54,7 +71,26 @@ describe('AdminSaveButtonComponent', () => {
     it('should assign state resource', () => {
       dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
 
-      expect(component.stateResource$).toBeObservable(singleCold(stateResource));
+      expect(component.stateResource$).toBeObservable(singleColdCompleted(stateResource));
+    });
+
+    it('should navigate on successful submit', () => {
+      isValidStateResourceMock.mockReturnValue(true);
+      const linkPath: string = faker.internet.url();
+      component.successLinkPath = linkPath;
+
+      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+      component.stateResource$.subscribe();
+
+      expect(navigationService.navigate).toHaveBeenCalledWith(linkPath);
+    });
+
+    it('should NOT navigate on invalid state resource', () => {
+      isValidStateResourceMock.mockReturnValue(false);
+      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+      component.stateResource$.subscribe();
+
+      expect(navigationService.navigate).not.toHaveBeenCalled();
     });
   });
 
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
index 60abd08c7f..7f0ff88dcd 100644
--- a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
+++ b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
@@ -1,10 +1,11 @@
 import { ADMIN_FORMSERVICE } from '@admin-client/shared';
-import { AbstractFormService, createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { NavigationService } from '@alfa-client/navigation-shared';
+import { AbstractFormService, createEmptyStateResource, isValidStateResource, StateResource } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
-import { Component, inject } from '@angular/core';
+import { Component, inject, Input } from '@angular/core';
 import { Resource } from '@ngxp/rest';
 import { ButtonWithSpinnerComponent } from '@ods/component';
-import { Observable, of } from 'rxjs';
+import { Observable, of, tap } from 'rxjs';
 
 @Component({
   selector: 'admin-save-button',
@@ -13,11 +14,20 @@ import { Observable, of } from 'rxjs';
   templateUrl: './admin-save-button.component.html',
 })
 export class AdminSaveButtonComponent {
-  private formService: AbstractFormService<Resource> = inject(ADMIN_FORMSERVICE);
+  @Input() successLinkPath: string;
+
+  private readonly formService: AbstractFormService<Resource> = inject(ADMIN_FORMSERVICE);
+  private readonly navigationService: NavigationService = inject(NavigationService);
 
   public stateResource$: Observable<StateResource<Resource>> = of(createEmptyStateResource<Resource>());
 
   public submit(): void {
-    this.stateResource$ = this.formService.submit();
+    this.stateResource$ = this.formService.submit().pipe(
+      tap((stateResource: StateResource<Resource>) => {
+        if (isValidStateResource(stateResource)) {
+          this.navigationService.navigate(this.successLinkPath);
+        }
+      }),
+    );
   }
 }
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
index 014109b6a8..146cfa8b5c 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
@@ -93,6 +93,14 @@ describe('StatistikContainerComponent', () => {
     });
   });
 
+  describe('on destroy', () => {
+    it('should refresh aggregation mapping list', () => {
+      component.ngOnDestroy();
+
+      expect(aggregationMappingService.refreshList).toHaveBeenCalled();
+    });
+  });
+
   describe('template', () => {
     describe('aggregation mapping list', () => {
       it('should exists', () => {
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
index 70db01b592..00226c7c85 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
@@ -25,7 +25,7 @@ import { AggregationMappingListResource, AggregationMappingService } from '@admi
 import { ROUTES } from '@admin-client/shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
-import { Component, inject, OnInit } from '@angular/core';
+import { Component, inject, OnDestroy, OnInit } from '@angular/core';
 import { RoutingButtonComponent } from '@ods/component';
 import { Observable } from 'rxjs';
 import { AggregationMappingListComponent } from '../aggregation-mapping-list/aggregation-mapping-list.component';
@@ -37,7 +37,7 @@ import { AggregationMappingListComponent } from '../aggregation-mapping-list/agg
   imports: [CommonModule, RoutingButtonComponent, AggregationMappingListComponent],
   providers: [AggregationMappingService],
 })
-export class StatistikContainerComponent implements OnInit {
+export class StatistikContainerComponent implements OnInit, OnDestroy {
   private service = inject(AggregationMappingService);
 
   public listStateResource$: Observable<StateResource<AggregationMappingListResource>>;
@@ -47,4 +47,8 @@ export class StatistikContainerComponent implements OnInit {
   ngOnInit(): void {
     this.listStateResource$ = this.service.getList();
   }
+
+  ngOnDestroy(): void {
+    this.service.refreshList();
+  }
 }
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
index a2922837c1..f81771feda 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
@@ -37,7 +37,7 @@
   </ods-button>
 
   <div class="mt-4 flex gap-4">
-    <admin-save-button />
+    <admin-save-button [successLinkPath]="Routes.STATISTIK" />
     <admin-cancel-button [linkPath]="Routes.STATISTIK" />
   </div>
 </div>
-- 
GitLab


From 243a85ebead0aa767f90a3cbb63366ccf3759e76 Mon Sep 17 00:00:00 2001
From: Alexander Reifschneider <alexander.reifschneider@mgm-tp.com>
Date: Wed, 12 Mar 2025 09:24:20 +0100
Subject: [PATCH 08/47] OZG-7473 Add responsive list styling

---
 ...gregation-mapping-list-item.component.html | 21 ++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
index 426085047e..931f646261 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -1,10 +1,17 @@
 <ods-list-item [path]="" [attr.data-test-id]="aggregationMapping.name | convertForDataTest">
-  <div class="flex-1 basis-1/2">
-    <div class="mb-2 flex flex-wrap items-center gap-3">
-      <h3 class="text-md font-semibold" data-test-class="fullname">{{ aggregationMapping.name }}</h3>
-    </div>
-    <!-- Remove null safe check operator after backend provides correct data. -->
-    <p>{{ aggregationMapping.formIdentifier?.formEngineName }}</p>
-    <p>{{ aggregationMapping.formIdentifier?.formId }}</p>
+  <dl class="flex-1 font-semibold">
+    <dt class="sr-only">Name</dt>
+    <dd data-test-class="fullname">{{ aggregationMapping.name }}</dd>
+  </dl>
+  <!-- Remove null safe check operator after backend provides correct data. -->
+  <div class="flex-1 flex-wrap">
+    <dl>
+      <dt class="sr-only">Formengine</dt>
+      <dd>{{ aggregationMapping.formIdentifier?.formEngineName }}</dd>
+    </dl>
+    <dl>
+      <dt class="sr-only">Form ID</dt>
+      <dd>{{ aggregationMapping.formIdentifier?.formId }}</dd>
+    </dl>
   </div>
 </ods-list-item>
-- 
GitLab


From 1471a29735673fe92f9aef7cd16a980ec5c17fc5 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Thu, 13 Mar 2025 09:48:27 +0100
Subject: [PATCH 09/47] OZG-7473 implement aggregation mapping patching

Sub task: OZG-7887
---
 .../apps/admin/src/app/app.component.spec.ts  |   2 +-
 .../apps/admin/src/app/app.component.ts       |   2 +-
 alfa-client/apps/admin/src/app/app.routes.ts  |  12 +-
 .../menu-container/menu/menu.component.html   |   2 +-
 .../lib/menu-container/menu/menu.component.ts |   2 +
 .../libs/admin/reporting-shared/src/index.ts  |   1 +
 ...gregation-mapping-list-resource.service.ts |  26 +++
 ...gregation-mapping-resource.service.spec.ts | 213 ++++++++++++++++++
 .../aggregation-mapping-resource.service.ts   |  75 ++++--
 .../src/lib/aggregation-mapping.linkrel.ts    |   4 +
 .../src/lib/aggregation-mapping.provider.ts   |  12 +-
 .../lib/aggregation-mapping.service.spec.ts   |  50 +++-
 .../src/lib/aggregation-mapping.service.ts    |  14 +-
 .../libs/admin/shared/src/lib/routes.ts       |   5 +-
 ...gregation-mapping-list-item.component.html |   2 +-
 ...gation-mapping-list-item.component.spec.ts |  23 +-
 ...aggregation-mapping-list-item.component.ts |   4 +-
 .../statistik-container.component.html        |   2 +-
 .../statistik-fields-form.component.html      |  76 ++++---
 .../statistik-fields-form.component.spec.ts   |  49 +++-
 .../statistik-fields-form.component.ts        |  11 +-
 .../statistik-fields.formservice.spec.ts      |  51 ++++-
 .../statistik-fields.formservice.ts           |  35 ++-
 23 files changed, 589 insertions(+), 84 deletions(-)
 create mode 100644 alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-list-resource.service.ts
 create mode 100644 alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts

diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts
index baa8c7fcc5..cc45121d96 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -297,7 +297,7 @@ describe('AppComponent', () => {
       it('should navigate to statistik if aggregation mapping link exists', () => {
         component._navigateByConfiguration(createConfigurationResource([ConfigurationLinkRel.AGGREGATION_MAPPINGS]));
 
-        expect(router.navigate).toHaveBeenCalledWith(['/statistik']);
+        expect(router.navigate).toHaveBeenCalledWith(['/aggregation-mapping']);
       });
 
       it('should navigate to unavailable page if no link exists', () => {
diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts
index 909b6cd198..989a4ad4b3 100644
--- a/alfa-client/apps/admin/src/app/app.component.ts
+++ b/alfa-client/apps/admin/src/app/app.component.ts
@@ -123,7 +123,7 @@ export class AppComponent implements OnInit {
     if (hasLink(configurationResource, ConfigurationLinkRel.SETTING)) {
       this.navigate(ROUTES.POSTFACH);
     } else if (hasLink(configurationResource, ConfigurationLinkRel.AGGREGATION_MAPPINGS)) {
-      this.navigate(ROUTES.STATISTIK);
+      this.navigate(ROUTES.AGGREGATION_MAPPING);
     } else {
       this.navigate(ROUTES.UNAVAILABLE);
     }
diff --git a/alfa-client/apps/admin/src/app/app.routes.ts b/alfa-client/apps/admin/src/app/app.routes.ts
index c5974993c2..2d21b25201 100644
--- a/alfa-client/apps/admin/src/app/app.routes.ts
+++ b/alfa-client/apps/admin/src/app/app.routes.ts
@@ -83,7 +83,7 @@ export const appRoutes: Route[] = [
     title: 'Unavailable',
   },
   {
-    path: ROUTES.STATISTIK,
+    path: ROUTES.AGGREGATION_MAPPING,
     component: StatistikPageComponent,
     title: 'Admin | Statistik',
     runGuardsAndResolvers: 'always',
@@ -91,7 +91,15 @@ export const appRoutes: Route[] = [
     data: <GuardData>{ linkRelName: ConfigurationLinkRel.AGGREGATION_MAPPINGS },
   },
   {
-    path: ROUTES.STATISTIK_NEU,
+    path: ROUTES.AGGREGATION_MAPPING_NEU,
+    component: StatistikFieldsFormPageComponent,
+    title: 'Admin | Statistik weitere Felder auswerten',
+    runGuardsAndResolvers: 'always',
+    canActivate: [configurationGuard],
+    data: <GuardData>{ linkRelName: ConfigurationLinkRel.AGGREGATION_MAPPINGS },
+  },
+  {
+    path: ROUTES.AGGREGATION_MAPPING_ID,
     component: StatistikFieldsFormPageComponent,
     title: 'Admin | Statistik weitere Felder auswerten',
     runGuardsAndResolvers: 'always',
diff --git a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html
index 0c1102a4c2..c319836e14 100644
--- a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html
+++ b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html
@@ -4,7 +4,7 @@
   </ods-nav-item>
 }
 @if (configurationStateResource.resource | hasLink: configurationLinkRel.AGGREGATION_MAPPINGS) {
-  <ods-nav-item data-test-id="statistik-navigation" caption="Statistik" path="/statistik">
+  <ods-nav-item data-test-id="statistik-navigation" caption="Statistik" [path]="'/' + ROUTES.AGGREGATION_MAPPING">
     <ods-statistic-icon icon />
   </ods-nav-item>
 }
diff --git a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts
index 0c9cddefff..c0845f3f13 100644
--- a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts
+++ b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts
@@ -1,4 +1,5 @@
 import { ConfigurationLinkRel, ConfigurationResource } from '@admin-client/configuration-shared';
+import { ROUTES } from '@admin-client/shared';
 import { HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
@@ -14,4 +15,5 @@ export class MenuComponent {
   @Input() configurationStateResource: StateResource<ConfigurationResource>;
 
   public readonly configurationLinkRel = ConfigurationLinkRel;
+  public readonly ROUTES = ROUTES;
 }
diff --git a/alfa-client/libs/admin/reporting-shared/src/index.ts b/alfa-client/libs/admin/reporting-shared/src/index.ts
index 44ab78233d..42e6a9bbe0 100644
--- a/alfa-client/libs/admin/reporting-shared/src/index.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/index.ts
@@ -1,3 +1,4 @@
+export * from './lib/aggregation-mapping-list-resource.service';
 export * from './lib/aggregation-mapping-resource.service';
 export * from './lib/aggregation-mapping.model';
 export * from './lib/aggregation-mapping.provider';
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-list-resource.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-list-resource.service.ts
new file mode 100644
index 0000000000..1378b74475
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-list-resource.service.ts
@@ -0,0 +1,26 @@
+import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
+import { ListResourceServiceConfig, ResourceListService, ResourceRepository } from '@alfa-client/tech-shared';
+import { AggregationMappingListLinkRel } from './aggregation-mapping.linkrel';
+import { AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
+
+export class AggregationMappingListResourceService extends ResourceListService<
+  ConfigurationResource,
+  AggregationMappingListResource,
+  AggregationMappingResource
+> {}
+
+export function createAggregationMappingListResourceService(
+  repository: ResourceRepository,
+  configurationService: ConfigurationService,
+) {
+  return new ResourceListService(buildConfig(configurationService), repository);
+}
+
+function buildConfig(configurationService: ConfigurationService): ListResourceServiceConfig<ConfigurationResource> {
+  return {
+    baseResource: configurationService.get(),
+    listLinkRel: ConfigurationLinkRel.AGGREGATION_MAPPINGS,
+    listResourceListLinkRel: AggregationMappingListLinkRel.LIST,
+    createLinkRel: AggregationMappingListLinkRel.SELF,
+  };
+}
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
new file mode 100644
index 0000000000..0b2f68fab6
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
@@ -0,0 +1,213 @@
+import { AggregationMappingResource } from '@admin-client/reporting-shared';
+import { ROUTES } from '@admin-client/shared';
+import { NavigationService, RouteData } from '@alfa-client/navigation-shared';
+import {
+  createEmptyStateResource,
+  createStateResource,
+  decodeUrlFromEmbedding,
+  ResourceRepository,
+  ResourceServiceConfig,
+  StateResource,
+} from '@alfa-client/tech-shared';
+import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
+import { UrlSegment } from '@angular/router';
+import { faker } from '@faker-js/faker';
+import { afterAll, expect } from '@jest/globals';
+import { ResourceUri } from '@ngxp/rest';
+import { Observable, of } from 'rxjs';
+import { createRouteData, createUrlSegment } from '../../../../navigation-shared/test/navigation-test-factory';
+import { singleColdCompleted } from '../../../../tech-shared/test/marbles';
+import { createAggregationMappingResource } from '../../test/aggregation-mapping';
+import * as module from './aggregation-mapping-resource.service';
+
+jest.mock('@alfa-client/tech-shared', () => ({
+  ...jest.requireActual('@alfa-client/tech-shared'),
+  decodeUrlFromEmbedding: jest.fn(),
+}));
+
+const decodeUrlFromEmbeddingMock: jest.Mock = decodeUrlFromEmbedding as jest.Mock;
+
+describe('AggregationMappingResourceService', () => {
+  let repository: Mock<ResourceRepository>;
+  let navigationService: Mock<NavigationService>;
+
+  beforeEach(() => {
+    repository = mock(ResourceRepository);
+    navigationService = mock(NavigationService);
+  });
+
+  describe('build config', () => {
+    const _getResourceByNavigationRoute: jest.SpyInstance = jest
+      .spyOn(module, '_getResourceByNavigationRoute')
+      .mockImplementation();
+
+    afterAll(() => {
+      _getResourceByNavigationRoute.mockRestore();
+    });
+
+    it('should get resource by navigation route', () => {
+      module._buildResourceServiceConfig(useFromMock(repository), useFromMock(navigationService));
+
+      expect(_getResourceByNavigationRoute).toHaveBeenCalled();
+    });
+
+    it('should have aggregation mapping static resource', () => {
+      const staticResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
+      _getResourceByNavigationRoute.mockReturnValue(of(staticResource));
+
+      const config: ResourceServiceConfig<AggregationMappingResource> = module._buildResourceServiceConfig(
+        useFromMock(repository),
+        useFromMock(navigationService),
+      );
+
+      expect(config.resource).toBeObservable(singleColdCompleted(staticResource));
+    });
+  });
+
+  describe('get resource by navigation route', () => {
+    const routeData: RouteData = createRouteData();
+    const _isAggregationMappingEditUrl: jest.SpyInstance = jest
+      .spyOn(module, '_isAggregationMappingEditUrl')
+      .mockImplementation();
+    const _getAggregationMappingResourceByRoute: jest.SpyInstance = jest
+      .spyOn(module, '_getAggregationMappingResourceByRoute')
+      .mockImplementation();
+
+    beforeEach(() => {
+      navigationService.getCurrentRouteData.mockReturnValue(of(routeData));
+    });
+
+    afterAll(() => {
+      _isAggregationMappingEditUrl.mockRestore();
+      _getAggregationMappingResourceByRoute.mockRestore();
+    });
+
+    it('should get current route data', () => {
+      module._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+
+      expect(navigationService.getCurrentRouteData).toHaveBeenCalled();
+    });
+
+    it('should check if url contains resource uri', () => {
+      module._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+
+      expect(_isAggregationMappingEditUrl).toHaveBeenCalled();
+    });
+
+    it('should get aggregation mapping resource by route', () => {
+      module._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+
+      expect(_getAggregationMappingResourceByRoute).toHaveBeenCalled();
+    });
+
+    it('should return aggregation mapping by route', () => {
+      const stateResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
+      _getAggregationMappingResourceByRoute.mockReturnValue(of(stateResource));
+      _isAggregationMappingEditUrl.mockReturnValue(true);
+
+      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = module._getResourceByNavigationRoute(
+        useFromMock(repository),
+        useFromMock(navigationService),
+      );
+
+      expect(resourceByRoute$).toBeObservable(singleColdCompleted(stateResource));
+    });
+
+    it('should return empty state resource', () => {
+      const stateResource: StateResource<AggregationMappingResource> = createEmptyStateResource();
+      _isAggregationMappingEditUrl.mockReturnValue(false);
+
+      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = module._getResourceByNavigationRoute(
+        useFromMock(repository),
+        useFromMock(navigationService),
+      );
+
+      expect(resourceByRoute$).toBeObservable(singleColdCompleted(stateResource));
+    });
+  });
+
+  describe('is aggregation mapping edit url', () => {
+    it.each([0, 1, 3])('should return false of wrong number of segments = %d', (numberOfSegments: number) => {
+      const routeData: RouteData = {
+        ...createRouteData(),
+        urlSegments: Array(numberOfSegments).fill(createUrlSegment()),
+      };
+
+      expect(module._isAggregationMappingEditUrl(routeData)).toBe(false);
+    });
+
+    it('should return false if first path is wrong', () => {
+      const routeData: RouteData = {
+        ...createRouteData(),
+        urlSegments: Array(2).fill(createUrlSegment()),
+      };
+
+      expect(module._isAggregationMappingEditUrl(routeData)).toBe(false);
+    });
+
+    it('should return false if second path is wrong', () => {
+      const firstUrlSegment: UrlSegment = createUrlSegment();
+      firstUrlSegment.path = ROUTES.AGGREGATION_MAPPING;
+      const secondUrlSegment: UrlSegment = createUrlSegment();
+      secondUrlSegment.path = 'neu';
+      const routeData: RouteData = {
+        ...createRouteData(),
+        urlSegments: [firstUrlSegment, secondUrlSegment],
+      };
+
+      expect(module._isAggregationMappingEditUrl(routeData)).toBe(false);
+    });
+
+    it('should return true', () => {
+      const firstUrlSegment: UrlSegment = createUrlSegment();
+      firstUrlSegment.path = ROUTES.AGGREGATION_MAPPING;
+      const secondUrlSegment: UrlSegment = createUrlSegment();
+      secondUrlSegment.path = faker.internet.url();
+      const routeData: RouteData = {
+        ...createRouteData(),
+        urlSegments: [firstUrlSegment, secondUrlSegment],
+      };
+
+      expect(module._isAggregationMappingEditUrl(routeData)).toBe(true);
+    });
+  });
+
+  describe('get aggregation mapping resource by route', () => {
+    const firstUrlSegment: UrlSegment = createUrlSegment();
+    firstUrlSegment.path = ROUTES.AGGREGATION_MAPPING;
+    const secondUrlSegment: UrlSegment = createUrlSegment();
+    secondUrlSegment.path = faker.internet.url();
+    const routeData: RouteData = {
+      ...createRouteData(),
+      urlSegments: [firstUrlSegment, secondUrlSegment],
+    };
+    const uri: ResourceUri = faker.internet.url();
+    const resource: AggregationMappingResource = createAggregationMappingResource();
+
+    beforeEach(() => {
+      decodeUrlFromEmbeddingMock.mockReturnValue(uri);
+      repository.getResource.mockReturnValue(of(resource));
+    });
+
+    it('should decode url', () => {
+      module._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
+
+      expect(decodeUrlFromEmbeddingMock).toHaveBeenCalledWith(secondUrlSegment.path);
+    });
+
+    it('should get resource', () => {
+      module._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
+
+      expect(repository.getResource).toHaveBeenCalledWith(uri);
+    });
+
+    it('should return state resource', () => {
+      const stateResource$: Observable<StateResource<AggregationMappingResource>> = module._getAggregationMappingResourceByRoute(
+        useFromMock(repository),
+        routeData,
+      );
+
+      expect(stateResource$).toBeObservable(singleColdCompleted(createStateResource(resource)));
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
index 65eb7a8e16..e4937c3eb7 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
@@ -1,26 +1,71 @@
-import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
-import { ListResourceServiceConfig, ResourceListService, ResourceRepository } from '@alfa-client/tech-shared';
-import { AggregationMappingListLinkRel } from './aggregation-mapping.linkrel';
-import { AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
+import { ROUTES } from '@admin-client/shared';
+import { NavigationService, RouteData } from '@alfa-client/navigation-shared';
+import {
+  ApiResourceService,
+  createEmptyStateResource,
+  createStateResource,
+  decodeUrlFromEmbedding,
+  ResourceRepository,
+  ResourceServiceConfig,
+  StateResource,
+} from '@alfa-client/tech-shared';
+import { UrlSegment } from '@angular/router';
+import { iif, map, Observable, of, switchMap } from 'rxjs';
+import * as module from './aggregation-mapping-resource.service';
+import { AggregationMappingLinkRel } from './aggregation-mapping.linkrel';
+import { AggregationMappingResource } from './aggregation-mapping.model';
 
-export class AggregationMappingListResourceService extends ResourceListService<
-  ConfigurationResource,
-  AggregationMappingListResource,
+export class AggregationMappingResourceService extends ApiResourceService<
+  AggregationMappingResource,
   AggregationMappingResource
 > {}
 
 export function createAggregationMappingResourceService(
   repository: ResourceRepository,
-  configurationService: ConfigurationService,
-) {
-  return new ResourceListService(buildConfig(configurationService), repository);
+  navigationService: NavigationService,
+): AggregationMappingResourceService {
+  return new AggregationMappingResourceService(_buildResourceServiceConfig(repository, navigationService), repository);
 }
 
-function buildConfig(configurationService: ConfigurationService): ListResourceServiceConfig<ConfigurationResource> {
+export function _buildResourceServiceConfig(
+  repository: ResourceRepository,
+  navigationService: NavigationService,
+): ResourceServiceConfig<AggregationMappingResource> {
+  module._getResourceByNavigationRoute(repository, navigationService);
   return {
-    baseResource: configurationService.get(),
-    listLinkRel: ConfigurationLinkRel.AGGREGATION_MAPPINGS,
-    listResourceListLinkRel: AggregationMappingListLinkRel.LIST,
-    createLinkRel: AggregationMappingListLinkRel.SELF,
+    resource: module._getResourceByNavigationRoute(repository, navigationService),
+    getLinkRel: AggregationMappingLinkRel.SELF,
+    edit: { linkRel: AggregationMappingLinkRel.SELF },
+    delete: { linkRel: AggregationMappingLinkRel.SELF },
   };
 }
+
+export function _getResourceByNavigationRoute(
+  repository: ResourceRepository,
+  navigationService: NavigationService,
+): Observable<StateResource<AggregationMappingResource>> {
+  return navigationService
+    .getCurrentRouteData()
+    .pipe(
+      switchMap((route: RouteData) =>
+        iif(
+          () => module._isAggregationMappingEditUrl(route),
+          module._getAggregationMappingResourceByRoute(repository, route),
+          of(createEmptyStateResource<AggregationMappingResource>()),
+        ),
+      ),
+    );
+}
+
+export function _isAggregationMappingEditUrl(route: RouteData): boolean {
+  const urlSegments: UrlSegment[] = route.urlSegments;
+  return urlSegments.length === 2 && urlSegments[0].path === ROUTES.AGGREGATION_MAPPING && urlSegments[1].path !== 'neu';
+}
+
+export function _getAggregationMappingResourceByRoute(
+  repository: ResourceRepository,
+  route: RouteData,
+): Observable<StateResource<AggregationMappingResource>> {
+  const uri: string = decodeUrlFromEmbedding(route.urlSegments[1].path);
+  return repository.getResource(uri).pipe(map((resource: AggregationMappingResource) => createStateResource(resource)));
+}
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel.ts
index a4a02bfd70..6aea64156f 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel.ts
@@ -2,3 +2,7 @@ export enum AggregationMappingListLinkRel {
   LIST = 'aggregationMappings',
   SELF = 'self',
 }
+
+export enum AggregationMappingLinkRel {
+  SELF = 'self',
+}
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.provider.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.provider.ts
index 888d7154e8..76d294de17 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.provider.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.provider.ts
@@ -1,8 +1,13 @@
+import { NavigationService } from '@alfa-client/navigation-shared';
 import { ResourceRepository } from '@alfa-client/tech-shared';
 import { Provider } from '@angular/core';
 import { ConfigurationService } from 'libs/admin/configuration-shared/src/lib/configuration.service';
 import {
   AggregationMappingListResourceService,
+  createAggregationMappingListResourceService,
+} from './aggregation-mapping-list-resource.service';
+import {
+  AggregationMappingResourceService,
   createAggregationMappingResourceService,
 } from './aggregation-mapping-resource.service';
 import { AggregationMappingService } from './aggregation-mapping.service';
@@ -10,8 +15,13 @@ import { AggregationMappingService } from './aggregation-mapping.service';
 export const AggregationMappingProvider: Provider[] = [
   {
     provide: AggregationMappingListResourceService,
-    useFactory: createAggregationMappingResourceService,
+    useFactory: createAggregationMappingListResourceService,
     deps: [ResourceRepository, ConfigurationService],
   },
+  {
+    provide: AggregationMappingResourceService,
+    useFactory: createAggregationMappingResourceService,
+    deps: [ResourceRepository, NavigationService],
+  },
   AggregationMappingService,
 ];
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
index d00e6923b0..0846feed2d 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
@@ -2,26 +2,33 @@ import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
 import { expect } from '@jest/globals';
-import { singleCold } from 'libs/tech-shared/test/marbles';
-import { Observable } from 'rxjs';
+import { singleCold, singleColdCompleted } from 'libs/tech-shared/test/marbles';
+import { Observable, of } from 'rxjs';
 import {
   createAggregationMapping,
   createAggregationMappingListResource,
   createAggregationMappingResource,
 } from '../../test/aggregation-mapping';
-import { AggregationMappingListResourceService } from './aggregation-mapping-resource.service';
+import { AggregationMappingListResourceService } from './aggregation-mapping-list-resource.service';
+import { AggregationMappingResourceService } from './aggregation-mapping-resource.service';
 import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
 import { AggregationMappingService } from './aggregation-mapping.service';
 
 describe('AggregationMappingService', () => {
   let service: AggregationMappingService;
   let listResourceService: Mock<AggregationMappingListResourceService>;
+  let resourceService: Mock<AggregationMappingResourceService>;
 
   beforeEach(() => {
     listResourceService = mock(AggregationMappingListResourceService);
+    resourceService = mock(AggregationMappingResourceService);
 
     TestBed.configureTestingModule({
-      providers: [AggregationMappingService, { provide: AggregationMappingListResourceService, useValue: listResourceService }],
+      providers: [
+        AggregationMappingService,
+        { provide: AggregationMappingListResourceService, useValue: listResourceService },
+        { provide: AggregationMappingResourceService, useValue: resourceService },
+      ],
     });
 
     service = TestBed.inject(AggregationMappingService);
@@ -87,4 +94,39 @@ describe('AggregationMappingService', () => {
       expect(listResourceService.refresh).toHaveBeenCalled();
     });
   });
+
+  describe('get by current url', () => {
+    const stateResource = createStateResource(createAggregationMappingResource());
+    beforeEach(() => {
+      resourceService.get = jest.fn().mockReturnValue(of(stateResource));
+    });
+
+    it('should call resource service', () => {
+      service.getByCurrentUrl();
+
+      expect(resourceService.get).toHaveBeenCalled();
+    });
+
+    it('should emit resource', () => {
+      expect(service.getByCurrentUrl()).toBeObservable(singleColdCompleted(stateResource));
+    });
+  });
+
+  describe('save', () => {
+    const aggregationMapping: AggregationMapping = createAggregationMapping();
+    const stateResource = createStateResource(createAggregationMappingResource());
+    beforeEach(() => {
+      resourceService.save = jest.fn().mockReturnValue(of(stateResource));
+    });
+
+    it('should call resource service', () => {
+      service.save(aggregationMapping);
+
+      expect(resourceService.save).toHaveBeenCalledWith(aggregationMapping);
+    });
+
+    it('should emit saved state resource', () => {
+      expect(service.save(aggregationMapping)).toBeObservable(singleColdCompleted(stateResource));
+    });
+  });
 });
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
index 00402e238c..19c85af76c 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
@@ -1,12 +1,14 @@
 import { StateResource } from '@alfa-client/tech-shared';
 import { inject, Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
-import { AggregationMappingListResourceService } from './aggregation-mapping-resource.service';
+import { AggregationMappingListResourceService } from './aggregation-mapping-list-resource.service';
+import { AggregationMappingResourceService } from './aggregation-mapping-resource.service';
 import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
 
 @Injectable()
 export class AggregationMappingService {
-  readonly listService = inject(AggregationMappingListResourceService);
+  private readonly listService = inject(AggregationMappingListResourceService);
+  private readonly resourceService = inject(AggregationMappingResourceService);
 
   public getList(): Observable<StateResource<AggregationMappingListResource>> {
     return this.listService.getList();
@@ -19,4 +21,12 @@ export class AggregationMappingService {
   public refreshList(): void {
     this.listService.refresh();
   }
+
+  public getByCurrentUrl(): Observable<StateResource<AggregationMappingResource>> {
+    return this.resourceService.get();
+  }
+
+  public save(aggregationMapping: AggregationMapping): Observable<StateResource<AggregationMappingResource>> {
+    return this.resourceService.save(aggregationMapping);
+  }
 }
diff --git a/alfa-client/libs/admin/shared/src/lib/routes.ts b/alfa-client/libs/admin/shared/src/lib/routes.ts
index 090a9f3a7d..cf1a221202 100644
--- a/alfa-client/libs/admin/shared/src/lib/routes.ts
+++ b/alfa-client/libs/admin/shared/src/lib/routes.ts
@@ -28,6 +28,7 @@ export enum ROUTES {
   BENUTZER_ID = 'benutzer/:userid',
   ORGANISATIONSEINHEITEN = 'organisationseinheiten',
   UNAVAILABLE = 'unavailable',
-  STATISTIK = 'statistik',
-  STATISTIK_NEU = 'statistik/neu',
+  AGGREGATION_MAPPING = 'aggregation-mapping',
+  AGGREGATION_MAPPING_NEU = 'aggregation-mapping/neu',
+  AGGREGATION_MAPPING_ID = 'aggregation-mapping/:aggregationMappingId',
 }
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
index 931f646261..777c081ff0 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -1,4 +1,4 @@
-<ods-list-item [path]="" [attr.data-test-id]="aggregationMapping.name | convertForDataTest">
+<ods-list-item [path]="aggregationMapping | toResourceUri" [attr.data-test-id]="aggregationMapping.name | convertForDataTest">
   <dl class="flex-1 font-semibold">
     <dt class="sr-only">Name</dt>
     <dd data-test-class="fullname">{{ aggregationMapping.name }}</dd>
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
index 7e48ac908d..18d620f575 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
@@ -1,21 +1,42 @@
+import { AggregationMappingResource } from '@admin-client/reporting-shared';
+import { ToResourceUriPipe } from '@alfa-client/tech-shared';
+import { getElementFromFixtureByType } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
+import { ListItemComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { createAggregationMappingResource } from '../../../../../reporting-shared/test/aggregation-mapping';
 import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item.component';
 
 describe('AggregationMappingListItemComponent', () => {
   let component: AggregationMappingListItemComponent;
   let fixture: ComponentFixture<AggregationMappingListItemComponent>;
 
+  const toResourceUriPipe: ToResourceUriPipe = new ToResourceUriPipe();
+  const aggregationMappingResource: AggregationMappingResource = createAggregationMappingResource();
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [AggregationMappingListItemComponent],
+      imports: [AggregationMappingListItemComponent, ToResourceUriPipe, MockComponent(ListItemComponent)],
     }).compileComponents();
 
     fixture = TestBed.createComponent(AggregationMappingListItemComponent);
     component = fixture.componentInstance;
+    component.aggregationMapping = aggregationMappingResource;
     fixture.detectChanges();
   });
 
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('template', () => {
+    describe('list item', () => {
+      it('should have inputs', () => {
+        const comp: ListItemComponent = getElementFromFixtureByType(fixture, ListItemComponent);
+
+        expect(comp.path).toEqual(toResourceUriPipe.transform(aggregationMappingResource));
+      });
+    });
+  });
 });
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
index c022babf73..6880096a77 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
@@ -1,5 +1,5 @@
 import { AggregationMappingResource } from '@admin-client/reporting-shared';
-import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe, ToResourceUriPipe } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
 import { ListItemComponent } from '@ods/system';
 
@@ -7,7 +7,7 @@ import { ListItemComponent } from '@ods/system';
   selector: 'admin-aggregation-mapping-list-item',
   standalone: true,
   templateUrl: './aggregation-mapping-list-item.component.html',
-  imports: [ConvertForDataTestPipe, ListItemComponent],
+  imports: [ConvertForDataTestPipe, ListItemComponent, ToResourceUriPipe],
   styles: [':host {@apply block}'],
 })
 export class AggregationMappingListItemComponent {
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
index bd98c2aaea..434802447a 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
@@ -26,7 +26,7 @@
 <h1 class="heading-1" data-test-id="statistik-header-text">Statistik</h1>
 <ods-routing-button
   class="my-4 w-fit"
-  [linkPath]="ROUTES.STATISTIK_NEU"
+  [linkPath]="ROUTES.AGGREGATION_MAPPING_NEU"
   text="Weitere Felder auswerten"
   dataTestId="weitere-felder-auswerten-button"
 />
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
index f81771feda..84f59729b8 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
@@ -1,43 +1,45 @@
 <h2 class="heading-2" data-test-id="statistik-fields-form-header-text">Felder zur Auswertung hinzufügen</h2>
 
-<div class="flex max-w-4xl flex-col gap-4">
-  <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-2">
-    <ods-text-editor
-      [formControlName]="StatistikFieldsFormService.FIELD_NAME"
-      label="Name *"
-      placeholder=""
-      data-test-id="statistik-name-text-editor"
-      dataTestId="statistik-name"
-    ></ods-text-editor>
-    <div [formGroupName]="StatistikFieldsFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
+<ods-spinner [stateResource]="aggregationMappingStateResource$ | async">
+  <div class="flex max-w-4xl flex-col gap-4">
+    <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-2">
       <ods-text-editor
-        [formControlName]="StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME"
-        label="Formengine *"
-        placeholder="Tragen Sie hier die Formengine des Formulars ein."
-        data-test-id="form-engine-name"
-        dataTestId="form-engine-name"
+        [formControlName]="StatistikFieldsFormService.FIELD_NAME"
+        label="Name *"
+        placeholder=""
+        data-test-id="statistik-name-text-editor"
+        dataTestId="statistik-name"
       ></ods-text-editor>
-      <ods-text-editor
-        [formControlName]="StatistikFieldsFormService.FIELD_FORM_ID"
-        label="FormID *"
-        placeholder="Tragen Sie hier die FormID des Formulars ein."
-        data-test-id="form-id"
-        dataTestId="form-id"
-      ></ods-text-editor>
-    </div>
-    <admin-statistik-fields-form-mapping />
-  </form>
-  <ods-button
-    text="Datenfeld hinzufügen"
-    dataTestId="add-mapping-button"
-    data-test-id="add-mapping"
-    (clickEmitter)="formService.addMapping()"
-  >
-    <ods-plus-icon icon class="fill-whitetext" />
-  </ods-button>
+      <div [formGroupName]="StatistikFieldsFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
+        <ods-text-editor
+          [formControlName]="StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME"
+          label="Formengine *"
+          placeholder="Tragen Sie hier die Formengine des Formulars ein."
+          data-test-id="form-engine-name"
+          dataTestId="form-engine-name"
+        ></ods-text-editor>
+        <ods-text-editor
+          [formControlName]="StatistikFieldsFormService.FIELD_FORM_ID"
+          label="FormID *"
+          placeholder="Tragen Sie hier die FormID des Formulars ein."
+          data-test-id="form-id"
+          dataTestId="form-id"
+        ></ods-text-editor>
+      </div>
+      <admin-statistik-fields-form-mapping />
+    </form>
+    <ods-button
+      text="Datenfeld hinzufügen"
+      dataTestId="add-mapping-button"
+      data-test-id="add-mapping"
+      (clickEmitter)="formService.addMapping()"
+    >
+      <ods-plus-icon icon class="fill-whitetext" />
+    </ods-button>
 
-  <div class="mt-4 flex gap-4">
-    <admin-save-button [successLinkPath]="Routes.STATISTIK" />
-    <admin-cancel-button [linkPath]="Routes.STATISTIK" />
+    <div class="mt-4 flex gap-4">
+      <admin-save-button [successLinkPath]="Routes.AGGREGATION_MAPPING" />
+      <admin-cancel-button [linkPath]="Routes.AGGREGATION_MAPPING" />
+    </div>
   </div>
-</div>
+</ods-spinner>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
index fc823f9d6c..5dc2a0eafa 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
@@ -1,12 +1,24 @@
-import { ADMIN_FORMSERVICE } from '@admin-client/shared';
-import { EMPTY_STRING } from '@alfa-client/tech-shared';
-import { dispatchEventFromFixture, existsAsHtmlElement, mock, Mock, MockEvent } from '@alfa-client/test-utils';
+import { AggregationMappingResource } from '@admin-client/reporting-shared';
+import { ADMIN_FORMSERVICE, ROUTES } from '@admin-client/shared';
+import { createStateResource, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
+import {
+  dispatchEventFromFixture,
+  existsAsHtmlElement,
+  getElementFromFixtureByType,
+  mock,
+  Mock,
+  MockEvent,
+} from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { expect } from '@jest/globals';
 import { TextEditorComponent } from '@ods/component';
 import { ButtonComponent, PlusIconComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
 import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../tech-shared/test/marbles';
+import { createAggregationMappingResource } from '../../../../reporting-shared/test/aggregation-mapping';
 import { AdminCancelButtonComponent } from '../../../../shared/src/lib/admin-cancel-button/admin-cancel-button.component';
 import { AdminSaveButtonComponent } from '../../../../shared/src/lib/admin-save-button/admin-save-button.component';
 import { StatistikFieldsFormComponent } from './statistik-fields-form.component';
@@ -21,6 +33,10 @@ describe('AdminStatistikFieldsFormComponent', () => {
   const formIdInputTestId: string = getDataTestIdOf('form-id');
   const addMappingButton: string = getDataTestIdOf('add-mapping');
 
+  const aggregationMappingStateResource: StateResource<AggregationMappingResource> = createStateResource(
+    createAggregationMappingResource(),
+  );
+
   const formBuilder: FormBuilder = new FormBuilder();
 
   let formService: Mock<StatistikFieldsFormService>;
@@ -35,6 +51,7 @@ describe('AdminStatistikFieldsFormComponent', () => {
     });
 
     formService = <any>{ ...mock(StatistikFieldsFormService), form };
+    formService.get = jest.fn().mockReturnValue(of(aggregationMappingStateResource));
 
     await TestBed.configureTestingModule({
       imports: [
@@ -73,6 +90,16 @@ describe('AdminStatistikFieldsFormComponent', () => {
     expect(component).toBeTruthy();
   });
 
+  describe('component', () => {
+    it('should get aggregation mapping from form service', () => {
+      expect(formService.get).toHaveBeenCalled();
+    });
+
+    it('should initial values', () => {
+      expect(component.aggregationMappingStateResource$).toBeObservable(singleColdCompleted(aggregationMappingStateResource));
+    });
+  });
+
   describe('template', () => {
     describe('form engine input', () => {
       it('should exists', () => {
@@ -109,5 +136,21 @@ describe('AdminStatistikFieldsFormComponent', () => {
         });
       });
     });
+
+    describe('save button', () => {
+      it('should have link path', () => {
+        const comp: AdminSaveButtonComponent = getElementFromFixtureByType(fixture, AdminSaveButtonComponent);
+
+        expect(comp.successLinkPath).toEqual(ROUTES.AGGREGATION_MAPPING);
+      });
+    });
+
+    describe('cancel button', () => {
+      it('should have link path', () => {
+        const comp: AdminCancelButtonComponent = getElementFromFixtureByType(fixture, AdminCancelButtonComponent);
+
+        expect(comp.linkPath).toEqual(ROUTES.AGGREGATION_MAPPING);
+      });
+    });
   });
 });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
index bd10b25953..9709c01258 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
@@ -1,8 +1,12 @@
+import { AggregationMappingResource } from '@admin-client/reporting-shared';
 import { ADMIN_FORMSERVICE, AdminCancelButtonComponent, AdminSaveButtonComponent, ROUTES } from '@admin-client/shared';
+import { StateResource } from '@alfa-client/tech-shared';
+import { AsyncPipe } from '@angular/common';
 import { Component, inject } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
-import { TextEditorComponent } from '@ods/component';
+import { SpinnerComponent, TextEditorComponent } from '@ods/component';
 import { ButtonComponent, PlusIconComponent } from '@ods/system';
+import { Observable } from 'rxjs';
 import { StatistikFieldsMappingsFormComponent } from './statistik-fields-mappings-form/statistik-fields-mappings-form.component';
 import { StatistikFieldsFormService } from './statistik-fields.formservice';
 
@@ -18,12 +22,17 @@ import { StatistikFieldsFormService } from './statistik-fields.formservice';
     AdminSaveButtonComponent,
     AdminCancelButtonComponent,
     StatistikFieldsMappingsFormComponent,
+    SpinnerComponent,
+    AsyncPipe,
   ],
   providers: [{ provide: ADMIN_FORMSERVICE, useClass: StatistikFieldsFormService }],
 })
 export class StatistikFieldsFormComponent {
   public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
 
+  public readonly aggregationMappingStateResource$: Observable<StateResource<AggregationMappingResource>> =
+    this.formService.get();
+
   public readonly StatistikFieldsFormService = StatistikFieldsFormService;
   public readonly Routes = ROUTES;
 }
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
index 2bb935d50e..45f57f4bef 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
@@ -26,8 +26,11 @@ import { createStateResource, EMPTY_STRING, StateResource } from '@alfa-client/t
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
 import { FormArray, FormControl, FormGroup } from '@angular/forms';
+import { expect } from '@jest/globals';
 import { createAggregationMapping, createAggregationMappingResource } from 'libs/admin/reporting-shared/test/aggregation-mapping';
+import { omit } from 'lodash-es';
 import { of } from 'rxjs';
+import { singleColdCompleted } from '../../../../../tech-shared/test/marbles';
 import { StatistikFieldsFormService } from './statistik-fields.formservice';
 
 describe('StatistikFieldsFormService', () => {
@@ -54,15 +57,26 @@ describe('StatistikFieldsFormService', () => {
 
     beforeEach(() => {
       service.create.mockReturnValue(of(stateResource));
+      service.save.mockReturnValue(of(stateResource));
     });
 
-    it('should call service', () => {
+    it('should create', () => {
+      formService.isPatch = jest.fn().mockReturnValue(false);
       formService.form = <any>createAggregationMapping();
 
       formService.submit();
 
       expect(service.create).toHaveBeenCalledWith(formService.form.value);
     });
+
+    it('should save', () => {
+      formService.isPatch = jest.fn().mockReturnValue(true);
+      formService.form = <any>createAggregationMapping();
+
+      formService.submit();
+
+      expect(service.save).toHaveBeenCalledWith(formService.form.value);
+    });
   });
 
   describe('add mapping', () => {
@@ -109,4 +123,39 @@ describe('StatistikFieldsFormService', () => {
       });
     });
   });
+
+  describe('get', () => {
+    const stateResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
+
+    beforeEach(() => {
+      service.getByCurrentUrl.mockReturnValue(of(stateResource));
+      formService._patchForm = jest.fn();
+    });
+
+    it('should get by current url', () => {
+      formService.get();
+
+      expect(service.getByCurrentUrl).toHaveBeenCalled();
+    });
+
+    it('should patch form', () => {
+      formService.get().subscribe();
+
+      expect(formService._patchForm).toHaveBeenCalledWith(stateResource.resource);
+    });
+
+    it('should emit state resource', () => {
+      expect(formService.get()).toBeObservable(singleColdCompleted(stateResource));
+    });
+  });
+
+  describe('patch form', () => {
+    const aggregationMappingResource: AggregationMappingResource = createAggregationMappingResource();
+
+    it('should patch', () => {
+      formService._patchForm(aggregationMappingResource);
+
+      expect(formService.form.value).toEqual(omit(aggregationMappingResource, '_links'));
+    });
+  });
 });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
index 67ecb47a0b..75d717dbc1 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
@@ -1,8 +1,8 @@
-import { AggregationMappingResource, AggregationMappingService } from '@admin-client/reporting-shared';
-import { AbstractFormService, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
+import { AggregationMappingResource, AggregationMappingService, FieldMapping } from '@admin-client/reporting-shared';
+import { AbstractFormService, EMPTY_STRING, isLoaded, StateResource } from '@alfa-client/tech-shared';
 import { inject, Injectable } from '@angular/core';
 import { FormArray, FormControl, FormGroup, UntypedFormGroup } from '@angular/forms';
-import { Observable } from 'rxjs';
+import { filter, Observable, tap } from 'rxjs';
 
 @Injectable()
 export class StatistikFieldsFormService extends AbstractFormService<AggregationMappingResource> {
@@ -14,7 +14,7 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
   public static readonly FIELD_MAPPING_SOURCE_PATH = 'sourcePath';
   public static readonly FIELD_MAPPING_TARGET_PATH = 'targetPath';
 
-  private service = inject(AggregationMappingService);
+  private readonly aggregationMappingService = inject(AggregationMappingService);
 
   protected initForm(): UntypedFormGroup {
     return this.formBuilder.group({
@@ -28,7 +28,10 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
   }
 
   protected doSubmit(): Observable<StateResource<AggregationMappingResource>> {
-    return this.service.create(this.getFormValue());
+    if (this.isPatch()) {
+      return this.aggregationMappingService.save(this.getFormValue());
+    }
+    return this.aggregationMappingService.create(this.getFormValue());
   }
 
   protected getPathPrefix(): string {
@@ -39,10 +42,10 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
     this.mappings.push(this.createArrayControl());
   }
 
-  private createArrayControl(): FormGroup {
+  private createArrayControl(sourcePath: string = EMPTY_STRING, targetPath: string = EMPTY_STRING): FormGroup {
     return new FormGroup({
-      [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
-      [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+      [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(sourcePath),
+      [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(targetPath),
     });
   }
 
@@ -53,4 +56,20 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
   public get mappings(): FormArray {
     return this.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS] as FormArray;
   }
+
+  public get(): Observable<StateResource<AggregationMappingResource>> {
+    return this.aggregationMappingService.getByCurrentUrl().pipe(
+      filter(isLoaded),
+      tap((stateResource: StateResource<AggregationMappingResource>) => this._patchForm(stateResource.resource)),
+    );
+  }
+
+  _patchForm(value: AggregationMappingResource): void {
+    this.patch(value);
+    const mappingsFormArray: FormArray = this.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS] as FormArray;
+    mappingsFormArray.clear();
+    value.mappings.forEach((mapping: FieldMapping) =>
+      mappingsFormArray.push(this.createArrayControl(mapping.sourcePath, mapping.targetPath)),
+    );
+  }
 }
-- 
GitLab


From 7adfdd16acf0eed514f56996166c024ed983f3be Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Thu, 13 Mar 2025 13:23:54 +0100
Subject: [PATCH 10/47] OZG-7473 fix unit tests

Sub task: OZG-7887
---
 ...gregation-mapping-resource.service.spec.ts | 40 +++++++++----------
 .../aggregation-mapping-resource.service.ts   |  9 ++---
 2 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
index 0b2f68fab6..b99b010505 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
@@ -18,7 +18,7 @@ import { Observable, of } from 'rxjs';
 import { createRouteData, createUrlSegment } from '../../../../navigation-shared/test/navigation-test-factory';
 import { singleColdCompleted } from '../../../../tech-shared/test/marbles';
 import { createAggregationMappingResource } from '../../test/aggregation-mapping';
-import * as module from './aggregation-mapping-resource.service';
+import * as mod from './aggregation-mapping-resource.service';
 
 jest.mock('@alfa-client/tech-shared', () => ({
   ...jest.requireActual('@alfa-client/tech-shared'),
@@ -37,16 +37,14 @@ describe('AggregationMappingResourceService', () => {
   });
 
   describe('build config', () => {
-    const _getResourceByNavigationRoute: jest.SpyInstance = jest
-      .spyOn(module, '_getResourceByNavigationRoute')
-      .mockImplementation();
+    const _getResourceByNavigationRoute: jest.SpyInstance = jest.spyOn(mod, '_getResourceByNavigationRoute').mockImplementation();
 
     afterAll(() => {
       _getResourceByNavigationRoute.mockRestore();
     });
 
     it('should get resource by navigation route', () => {
-      module._buildResourceServiceConfig(useFromMock(repository), useFromMock(navigationService));
+      mod._buildResourceServiceConfig(useFromMock(repository), useFromMock(navigationService));
 
       expect(_getResourceByNavigationRoute).toHaveBeenCalled();
     });
@@ -55,7 +53,7 @@ describe('AggregationMappingResourceService', () => {
       const staticResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
       _getResourceByNavigationRoute.mockReturnValue(of(staticResource));
 
-      const config: ResourceServiceConfig<AggregationMappingResource> = module._buildResourceServiceConfig(
+      const config: ResourceServiceConfig<AggregationMappingResource> = mod._buildResourceServiceConfig(
         useFromMock(repository),
         useFromMock(navigationService),
       );
@@ -66,11 +64,9 @@ describe('AggregationMappingResourceService', () => {
 
   describe('get resource by navigation route', () => {
     const routeData: RouteData = createRouteData();
-    const _isAggregationMappingEditUrl: jest.SpyInstance = jest
-      .spyOn(module, '_isAggregationMappingEditUrl')
-      .mockImplementation();
+    const _isAggregationMappingEditUrl: jest.SpyInstance = jest.spyOn(mod, '_isAggregationMappingEditUrl').mockImplementation();
     const _getAggregationMappingResourceByRoute: jest.SpyInstance = jest
-      .spyOn(module, '_getAggregationMappingResourceByRoute')
+      .spyOn(mod, '_getAggregationMappingResourceByRoute')
       .mockImplementation();
 
     beforeEach(() => {
@@ -83,19 +79,19 @@ describe('AggregationMappingResourceService', () => {
     });
 
     it('should get current route data', () => {
-      module._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+      mod._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
 
       expect(navigationService.getCurrentRouteData).toHaveBeenCalled();
     });
 
     it('should check if url contains resource uri', () => {
-      module._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+      mod._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
 
       expect(_isAggregationMappingEditUrl).toHaveBeenCalled();
     });
 
     it('should get aggregation mapping resource by route', () => {
-      module._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+      mod._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
 
       expect(_getAggregationMappingResourceByRoute).toHaveBeenCalled();
     });
@@ -105,7 +101,7 @@ describe('AggregationMappingResourceService', () => {
       _getAggregationMappingResourceByRoute.mockReturnValue(of(stateResource));
       _isAggregationMappingEditUrl.mockReturnValue(true);
 
-      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = module._getResourceByNavigationRoute(
+      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = mod._getResourceByNavigationRoute(
         useFromMock(repository),
         useFromMock(navigationService),
       );
@@ -117,7 +113,7 @@ describe('AggregationMappingResourceService', () => {
       const stateResource: StateResource<AggregationMappingResource> = createEmptyStateResource();
       _isAggregationMappingEditUrl.mockReturnValue(false);
 
-      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = module._getResourceByNavigationRoute(
+      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = mod._getResourceByNavigationRoute(
         useFromMock(repository),
         useFromMock(navigationService),
       );
@@ -133,7 +129,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: Array(numberOfSegments).fill(createUrlSegment()),
       };
 
-      expect(module._isAggregationMappingEditUrl(routeData)).toBe(false);
+      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(false);
     });
 
     it('should return false if first path is wrong', () => {
@@ -142,7 +138,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: Array(2).fill(createUrlSegment()),
       };
 
-      expect(module._isAggregationMappingEditUrl(routeData)).toBe(false);
+      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(false);
     });
 
     it('should return false if second path is wrong', () => {
@@ -155,7 +151,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: [firstUrlSegment, secondUrlSegment],
       };
 
-      expect(module._isAggregationMappingEditUrl(routeData)).toBe(false);
+      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(false);
     });
 
     it('should return true', () => {
@@ -168,7 +164,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: [firstUrlSegment, secondUrlSegment],
       };
 
-      expect(module._isAggregationMappingEditUrl(routeData)).toBe(true);
+      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(true);
     });
   });
 
@@ -190,19 +186,19 @@ describe('AggregationMappingResourceService', () => {
     });
 
     it('should decode url', () => {
-      module._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
+      mod._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
 
       expect(decodeUrlFromEmbeddingMock).toHaveBeenCalledWith(secondUrlSegment.path);
     });
 
     it('should get resource', () => {
-      module._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
+      mod._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
 
       expect(repository.getResource).toHaveBeenCalledWith(uri);
     });
 
     it('should return state resource', () => {
-      const stateResource$: Observable<StateResource<AggregationMappingResource>> = module._getAggregationMappingResourceByRoute(
+      const stateResource$: Observable<StateResource<AggregationMappingResource>> = mod._getAggregationMappingResourceByRoute(
         useFromMock(repository),
         routeData,
       );
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
index e4937c3eb7..d6d4ed3377 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
@@ -11,7 +11,7 @@ import {
 } from '@alfa-client/tech-shared';
 import { UrlSegment } from '@angular/router';
 import { iif, map, Observable, of, switchMap } from 'rxjs';
-import * as module from './aggregation-mapping-resource.service';
+import * as mod from './aggregation-mapping-resource.service';
 import { AggregationMappingLinkRel } from './aggregation-mapping.linkrel';
 import { AggregationMappingResource } from './aggregation-mapping.model';
 
@@ -31,9 +31,8 @@ export function _buildResourceServiceConfig(
   repository: ResourceRepository,
   navigationService: NavigationService,
 ): ResourceServiceConfig<AggregationMappingResource> {
-  module._getResourceByNavigationRoute(repository, navigationService);
   return {
-    resource: module._getResourceByNavigationRoute(repository, navigationService),
+    resource: mod._getResourceByNavigationRoute(repository, navigationService),
     getLinkRel: AggregationMappingLinkRel.SELF,
     edit: { linkRel: AggregationMappingLinkRel.SELF },
     delete: { linkRel: AggregationMappingLinkRel.SELF },
@@ -49,8 +48,8 @@ export function _getResourceByNavigationRoute(
     .pipe(
       switchMap((route: RouteData) =>
         iif(
-          () => module._isAggregationMappingEditUrl(route),
-          module._getAggregationMappingResourceByRoute(repository, route),
+          () => mod._isAggregationMappingEditUrl(route),
+          mod._getAggregationMappingResourceByRoute(repository, route),
           of(createEmptyStateResource<AggregationMappingResource>()),
         ),
       ),
-- 
GitLab


From e92580c3e10f77c2e2d2470b53a99f98d5462483 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Thu, 13 Mar 2025 14:32:05 +0100
Subject: [PATCH 11/47] OZG-7473 rename

Sub task: OZG-7887
---
 ...gregation-mapping-resource.service.spec.ts | 38 ++++++++++---------
 .../aggregation-mapping-resource.service.ts   |  8 ++--
 2 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
index b99b010505..4faae6e022 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
@@ -18,7 +18,7 @@ import { Observable, of } from 'rxjs';
 import { createRouteData, createUrlSegment } from '../../../../navigation-shared/test/navigation-test-factory';
 import { singleColdCompleted } from '../../../../tech-shared/test/marbles';
 import { createAggregationMappingResource } from '../../test/aggregation-mapping';
-import * as mod from './aggregation-mapping-resource.service';
+import * as self from './aggregation-mapping-resource.service';
 
 jest.mock('@alfa-client/tech-shared', () => ({
   ...jest.requireActual('@alfa-client/tech-shared'),
@@ -37,14 +37,16 @@ describe('AggregationMappingResourceService', () => {
   });
 
   describe('build config', () => {
-    const _getResourceByNavigationRoute: jest.SpyInstance = jest.spyOn(mod, '_getResourceByNavigationRoute').mockImplementation();
+    const _getResourceByNavigationRoute: jest.SpyInstance = jest
+      .spyOn(self, '_getResourceByNavigationRoute')
+      .mockImplementation();
 
     afterAll(() => {
       _getResourceByNavigationRoute.mockRestore();
     });
 
     it('should get resource by navigation route', () => {
-      mod._buildResourceServiceConfig(useFromMock(repository), useFromMock(navigationService));
+      self._buildResourceServiceConfig(useFromMock(repository), useFromMock(navigationService));
 
       expect(_getResourceByNavigationRoute).toHaveBeenCalled();
     });
@@ -53,7 +55,7 @@ describe('AggregationMappingResourceService', () => {
       const staticResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
       _getResourceByNavigationRoute.mockReturnValue(of(staticResource));
 
-      const config: ResourceServiceConfig<AggregationMappingResource> = mod._buildResourceServiceConfig(
+      const config: ResourceServiceConfig<AggregationMappingResource> = self._buildResourceServiceConfig(
         useFromMock(repository),
         useFromMock(navigationService),
       );
@@ -64,9 +66,9 @@ describe('AggregationMappingResourceService', () => {
 
   describe('get resource by navigation route', () => {
     const routeData: RouteData = createRouteData();
-    const _isAggregationMappingEditUrl: jest.SpyInstance = jest.spyOn(mod, '_isAggregationMappingEditUrl').mockImplementation();
+    const _isAggregationMappingEditUrl: jest.SpyInstance = jest.spyOn(self, '_isAggregationMappingEditUrl').mockImplementation();
     const _getAggregationMappingResourceByRoute: jest.SpyInstance = jest
-      .spyOn(mod, '_getAggregationMappingResourceByRoute')
+      .spyOn(self, '_getAggregationMappingResourceByRoute')
       .mockImplementation();
 
     beforeEach(() => {
@@ -79,19 +81,19 @@ describe('AggregationMappingResourceService', () => {
     });
 
     it('should get current route data', () => {
-      mod._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+      self._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
 
       expect(navigationService.getCurrentRouteData).toHaveBeenCalled();
     });
 
     it('should check if url contains resource uri', () => {
-      mod._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+      self._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
 
       expect(_isAggregationMappingEditUrl).toHaveBeenCalled();
     });
 
     it('should get aggregation mapping resource by route', () => {
-      mod._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
+      self._getResourceByNavigationRoute(useFromMock(repository), useFromMock(navigationService)).subscribe();
 
       expect(_getAggregationMappingResourceByRoute).toHaveBeenCalled();
     });
@@ -101,7 +103,7 @@ describe('AggregationMappingResourceService', () => {
       _getAggregationMappingResourceByRoute.mockReturnValue(of(stateResource));
       _isAggregationMappingEditUrl.mockReturnValue(true);
 
-      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = mod._getResourceByNavigationRoute(
+      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = self._getResourceByNavigationRoute(
         useFromMock(repository),
         useFromMock(navigationService),
       );
@@ -113,7 +115,7 @@ describe('AggregationMappingResourceService', () => {
       const stateResource: StateResource<AggregationMappingResource> = createEmptyStateResource();
       _isAggregationMappingEditUrl.mockReturnValue(false);
 
-      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = mod._getResourceByNavigationRoute(
+      const resourceByRoute$: Observable<StateResource<AggregationMappingResource>> = self._getResourceByNavigationRoute(
         useFromMock(repository),
         useFromMock(navigationService),
       );
@@ -129,7 +131,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: Array(numberOfSegments).fill(createUrlSegment()),
       };
 
-      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(false);
+      expect(self._isAggregationMappingEditUrl(routeData)).toBe(false);
     });
 
     it('should return false if first path is wrong', () => {
@@ -138,7 +140,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: Array(2).fill(createUrlSegment()),
       };
 
-      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(false);
+      expect(self._isAggregationMappingEditUrl(routeData)).toBe(false);
     });
 
     it('should return false if second path is wrong', () => {
@@ -151,7 +153,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: [firstUrlSegment, secondUrlSegment],
       };
 
-      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(false);
+      expect(self._isAggregationMappingEditUrl(routeData)).toBe(false);
     });
 
     it('should return true', () => {
@@ -164,7 +166,7 @@ describe('AggregationMappingResourceService', () => {
         urlSegments: [firstUrlSegment, secondUrlSegment],
       };
 
-      expect(mod._isAggregationMappingEditUrl(routeData)).toBe(true);
+      expect(self._isAggregationMappingEditUrl(routeData)).toBe(true);
     });
   });
 
@@ -186,19 +188,19 @@ describe('AggregationMappingResourceService', () => {
     });
 
     it('should decode url', () => {
-      mod._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
+      self._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
 
       expect(decodeUrlFromEmbeddingMock).toHaveBeenCalledWith(secondUrlSegment.path);
     });
 
     it('should get resource', () => {
-      mod._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
+      self._getAggregationMappingResourceByRoute(useFromMock(repository), routeData);
 
       expect(repository.getResource).toHaveBeenCalledWith(uri);
     });
 
     it('should return state resource', () => {
-      const stateResource$: Observable<StateResource<AggregationMappingResource>> = mod._getAggregationMappingResourceByRoute(
+      const stateResource$: Observable<StateResource<AggregationMappingResource>> = self._getAggregationMappingResourceByRoute(
         useFromMock(repository),
         routeData,
       );
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
index d6d4ed3377..0bfa0689a8 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
@@ -11,7 +11,7 @@ import {
 } from '@alfa-client/tech-shared';
 import { UrlSegment } from '@angular/router';
 import { iif, map, Observable, of, switchMap } from 'rxjs';
-import * as mod from './aggregation-mapping-resource.service';
+import * as self from './aggregation-mapping-resource.service';
 import { AggregationMappingLinkRel } from './aggregation-mapping.linkrel';
 import { AggregationMappingResource } from './aggregation-mapping.model';
 
@@ -32,7 +32,7 @@ export function _buildResourceServiceConfig(
   navigationService: NavigationService,
 ): ResourceServiceConfig<AggregationMappingResource> {
   return {
-    resource: mod._getResourceByNavigationRoute(repository, navigationService),
+    resource: self._getResourceByNavigationRoute(repository, navigationService),
     getLinkRel: AggregationMappingLinkRel.SELF,
     edit: { linkRel: AggregationMappingLinkRel.SELF },
     delete: { linkRel: AggregationMappingLinkRel.SELF },
@@ -48,8 +48,8 @@ export function _getResourceByNavigationRoute(
     .pipe(
       switchMap((route: RouteData) =>
         iif(
-          () => mod._isAggregationMappingEditUrl(route),
-          mod._getAggregationMappingResourceByRoute(repository, route),
+          () => self._isAggregationMappingEditUrl(route),
+          self._getAggregationMappingResourceByRoute(repository, route),
           of(createEmptyStateResource<AggregationMappingResource>()),
         ),
       ),
-- 
GitLab


From 8d2314f8f18cea25401eb2015ecfdd139cbc1cfb Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 16 Mar 2025 16:29:17 +0100
Subject: [PATCH 12/47] OZG-7473 add validation

Sub task: OZG-7889
---
 .../statistik-fields-form.component.html      |  9 ++--
 .../statistik-fields-form.component.ts        |  2 +-
 ...tatistik-field-mapping-form.component.html |  6 ++-
 .../statistik-fields.formservice.ts           |  2 +-
 .../resource/list-resource.service.spec.ts    | 23 +++++++++--
 .../src/lib/resource/list-resource.service.ts | 26 ++++++------
 .../validation/tech.validation.util.spec.ts   | 27 +++++-------
 .../lib/validation/tech.validation.util.ts    | 41 +++++++------------
 8 files changed, 70 insertions(+), 66 deletions(-)

diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
index 84f59729b8..b9f078d75e 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
@@ -5,23 +5,26 @@
     <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-2">
       <ods-text-editor
         [formControlName]="StatistikFieldsFormService.FIELD_NAME"
-        label="Name *"
+        label="Name"
         placeholder=""
+        isRequired="true"
         data-test-id="statistik-name-text-editor"
         dataTestId="statistik-name"
       ></ods-text-editor>
       <div [formGroupName]="StatistikFieldsFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
         <ods-text-editor
           [formControlName]="StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME"
-          label="Formengine *"
+          label="Formengine"
           placeholder="Tragen Sie hier die Formengine des Formulars ein."
+          isRequired="true"
           data-test-id="form-engine-name"
           dataTestId="form-engine-name"
         ></ods-text-editor>
         <ods-text-editor
           [formControlName]="StatistikFieldsFormService.FIELD_FORM_ID"
-          label="FormID *"
+          label="FormID"
           placeholder="Tragen Sie hier die FormID des Formulars ein."
+          isRequired="true"
           data-test-id="form-id"
           dataTestId="form-id"
         ></ods-text-editor>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
index 9709c01258..b5f78af0ec 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
@@ -18,12 +18,12 @@ import { StatistikFieldsFormService } from './statistik-fields.formservice';
     ButtonComponent,
     PlusIconComponent,
     ReactiveFormsModule,
-    TextEditorComponent,
     AdminSaveButtonComponent,
     AdminCancelButtonComponent,
     StatistikFieldsMappingsFormComponent,
     SpinnerComponent,
     AsyncPipe,
+    TextEditorComponent,
   ],
   providers: [{ provide: ADMIN_FORMSERVICE, useClass: StatistikFieldsFormService }],
 })
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
index b7af910dbf..05dd38f408 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
@@ -19,15 +19,17 @@
         <ods-text-editor
           class="flex-1"
           formControlName="sourcePath"
-          label="Pfad *"
+          label="Pfad"
           placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
+          isRequired="true"
           [dataTestId]="'source-mapping-field-' + index"
           [attr.data-test-id]="'source-mapping-field-' + index"
         ></ods-text-editor>
         <ods-text-editor
           class="flex-1"
           formControlName="targetPath"
-          label="Zielfeld *"
+          label="Zielfeld"
+          isRequired="true"
           placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
           [dataTestId]="'target-mapping-field-' + index"
           [attr.data-test-id]="'target-mapping-field-' + index"
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
index 75d717dbc1..10ba7d8039 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
@@ -35,7 +35,7 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
   }
 
   protected getPathPrefix(): string {
-    return 'settingBody';
+    return EMPTY_STRING;
   }
 
   public addMapping(): void {
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
index aa2dee9b69..648099dffa 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
@@ -29,13 +29,16 @@ import { cold } from 'jest-marbles';
 import { DummyLinkRel, DummyListLinkRel } from 'libs/tech-shared/test/dummy';
 import { createDummyListResource, createDummyResource, createFilledDummyListResource } from 'libs/tech-shared/test/resource';
 import { BehaviorSubject, Observable, of } from 'rxjs';
-import { multipleCold, singleCold, singleHot } from '../../../test/marbles';
+import { multipleCold, singleCold, singleColdCompleted, singleHot } from '../../../test/marbles';
 import { ResourceListService } from './list-resource.service';
 import { CreateResourceData, LinkRelationName, ListItemResource, ListResourceServiceConfig } from './resource.model';
 import { ResourceRepository } from './resource.repository';
-import { ListResource, StateResource, createEmptyStateResource, createStateResource } from './resource.util';
-
 import * as ResourceUtil from './resource.util';
+import { createEmptyStateResource, createErrorStateResource, createStateResource, ListResource, StateResource } from './resource.util';
+
+import { ProblemDetail } from '@alfa-client/tech-shared';
+import { expect } from '@jest/globals';
+import { createProblemDetail } from '../../../test/error';
 
 describe('ListResourceService', () => {
   let service: ResourceListService<Resource, ListResource, ListItemResource>;
@@ -350,6 +353,20 @@ describe('ListResourceService', () => {
     });
   });
 
+  describe('handle error', () => {
+    it('should return error state resource on unprocessable entity', () => {
+      const error: ProblemDetail = createProblemDetail();
+
+      expect(service._handleError(error)).toBeObservable(singleColdCompleted(createErrorStateResource(error)));
+    });
+
+    it('should throw error', () => {
+      const error: ProblemDetail = { ...createProblemDetail(), status: 500 };
+
+      expect(service._handleError(error)).toBeObservable(cold('#', null, error));
+    });
+  });
+
   describe('select', () => {
     const selfHref: ResourceUri = 'dummySelfHref';
     const dummyResource: Resource = createResourceWithUri(selfHref);
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
index 852a8299c5..ae32eafd97 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
@@ -21,24 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Resource, ResourceUri, getUrl, hasLink } from '@ngxp/rest';
+import { getUrl, hasLink, Resource, ResourceUri } from '@ngxp/rest';
 import { isEqual, isNil, isNull } from 'lodash-es';
-import { BehaviorSubject, Observable, combineLatest, debounceTime, filter, first, map, startWith, tap } from 'rxjs';
+import { BehaviorSubject, catchError, combineLatest, debounceTime, filter, first, map, Observable, of, startWith, tap, throwError, } from 'rxjs';
+import { isUnprocessableEntity } from '../http.util';
+import { ProblemDetail } from '../tech.model';
 import { isNotNull, isNotUndefined } from '../tech.util';
 import { CreateResourceData, ListItemResource, ListResourceServiceConfig } from './resource.model';
 import { ResourceRepository } from './resource.repository';
 import { mapToFirst, mapToResource } from './resource.rxjs.operator';
-import {
-  ListResource,
-  StateResource,
-  createEmptyStateResource,
-  createStateResource,
-  doIfLoadingRequired,
-  getEmbeddedResources,
-  isInvalidResourceCombination,
-  isLoadingRequired,
-  isStateResoureStable,
-} from './resource.util';
+import { createEmptyStateResource, createErrorStateResource, createStateResource, doIfLoadingRequired, getEmbeddedResources, isInvalidResourceCombination, isLoadingRequired, isStateResoureStable, ListResource, StateResource, } from './resource.util';
 
 /**
  * B = Type of baseresource
@@ -111,6 +103,7 @@ export class ResourceListService<B extends Resource, T extends ListResource, I e
     return this.repository.createResource(this.buildCreateResourceData(toCreate, this.config.createLinkRel)).pipe(
       map((listItemResource: I) => createStateResource(listItemResource)),
       startWith(createEmptyStateResource<I>(true)),
+      catchError((error: ProblemDetail) => this._handleError(error)),
     );
   }
 
@@ -131,6 +124,13 @@ export class ResourceListService<B extends Resource, T extends ListResource, I e
     return this.hasLinkRel(this.config.createLinkRel);
   }
 
+  _handleError(error: ProblemDetail): Observable<StateResource<I>> {
+    if (isUnprocessableEntity(error.status)) {
+      return of(createErrorStateResource(error));
+    }
+    return throwError(() => error);
+  }
+
   public select(uri: ResourceUri): void {
     this.setSelectedResourceLoading();
     this.repository
diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts
index 32ce38f3c4..f5a6a56fb0 100644
--- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts
@@ -26,7 +26,7 @@ import { faker } from '@faker-js/faker';
 import { createInvalidParam, createIssue, createProblemDetail } from '../../../test/error';
 import { InvalidParam, Issue } from '../tech.model';
 import { VALIDATION_MESSAGES, ValidationMessageCode } from './tech.validation.messages';
-import { getControlForInvalidParam, getControlForIssue, getFieldPath, getMessageForInvalidParam, getMessageForIssue, getMessageReason, setInvalidParamValidationError, setIssueValidationError } from './tech.validation.util';
+import { getControlForInvalidParam, getControlForIssue, getFieldPath, getMessageForInvalidParam, getMessageForIssue, getMessageReason, setInvalidParamValidationError, setIssueValidationError, } from './tech.validation.util';
 
 describe('ValidationUtils', () => {
   const baseField1Control: FormControl = new UntypedFormControl();
@@ -44,7 +44,7 @@ describe('ValidationUtils', () => {
   describe('set issue validation error', () => {
     describe('get control for issue', () => {
       it('should return base field control', () => {
-        const issue: Issue = { ...createIssue(), field: 'class.resource.baseField1' };
+        const issue: Issue = { ...createIssue(), field: 'baseField1' };
 
         const control: AbstractControl = getControlForIssue(form, issue);
 
@@ -69,7 +69,7 @@ describe('ValidationUtils', () => {
     });
 
     describe('in base field', () => {
-      const issue: Issue = { ...createIssue(), field: 'class.resource.baseField1' };
+      const issue: Issue = { ...createIssue(), field: 'baseField1' };
 
       it('should set error in control', () => {
         setIssueValidationError(form, issue);
@@ -144,7 +144,7 @@ describe('ValidationUtils', () => {
       it('should return base field control', () => {
         const invalidParam: InvalidParam = {
           ...createInvalidParam(),
-          name: 'class.resource.baseField1',
+          name: 'baseField1',
         };
 
         const control: AbstractControl = getControlForInvalidParam(form, invalidParam);
@@ -155,7 +155,7 @@ describe('ValidationUtils', () => {
       it('should return sub group field', () => {
         const invalidParam: InvalidParam = {
           ...createInvalidParam(),
-          name: 'class.resource.subGroup.subGroupField1',
+          name: 'resource.subGroup.subGroupField1',
         };
 
         const control: AbstractControl = getControlForInvalidParam(form, invalidParam, 'resource');
@@ -166,7 +166,7 @@ describe('ValidationUtils', () => {
       it('should ignore path prefix', () => {
         const invalidParam: InvalidParam = {
           ...createInvalidParam(),
-          name: 'class.resource.baseField1',
+          name: 'resource.baseField1',
         };
 
         const control: AbstractControl = getControlForInvalidParam(form, invalidParam, 'resource');
@@ -178,7 +178,7 @@ describe('ValidationUtils', () => {
     describe('in base field', () => {
       const invalidParam: InvalidParam = {
         ...createInvalidParam(),
-        name: 'class.resource.baseField1',
+        name: 'baseField1',
       };
 
       it('should set error in control', () => {
@@ -209,7 +209,7 @@ describe('ValidationUtils', () => {
     describe('in subGroup Field', () => {
       const invalidParam: InvalidParam = {
         ...createInvalidParam(),
-        name: 'class.resource.subGroup.subGroupField1',
+        name: 'resource.subGroup.subGroupField1',
       };
 
       it('should set error in control', () => {
@@ -243,12 +243,9 @@ describe('ValidationUtils', () => {
     });
 
     it('should return field from full path when resource is undefined', () => {
-      const fieldPath: string = 'field1';
-      const fullPath: string = `${backendClassName}.${resource}.${fieldPath}`;
-
-      const result: string = getFieldPath(fullPath, undefined);
+      const result: string = getFieldPath('field1', undefined);
 
-      expect(result).toBe(fieldPath);
+      expect(result).toBe('field1');
     });
 
     it('should return field from field when resource is undefined', () => {
@@ -309,9 +306,7 @@ describe('ValidationUtils', () => {
         ...invalidParam,
         reason: ValidationMessageCode.FIELD_INVALID,
       });
-      expect(message).toEqual(
-        VALIDATION_MESSAGES[ValidationMessageCode.FIELD_INVALID].replace('{field}', label),
-      );
+      expect(message).toEqual(VALIDATION_MESSAGES[ValidationMessageCode.FIELD_INVALID].replace('{field}', label));
     });
 
     it('should return message with placeholders', () => {
diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts
index b0cb78f8a1..8ea81cca8d 100644
--- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts
+++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts
@@ -31,28 +31,18 @@ export function isValidationError(issue: Issue): boolean {
   return issue.messageCode.includes('javax.validation.constraints');
 }
 
-export function setIssueValidationError(
-  form: UntypedFormGroup,
-  issue: Issue,
-  pathPrefix?: string,
-): void {
+export function setIssueValidationError(form: UntypedFormGroup, issue: Issue, pathPrefix?: string): void {
   const control: AbstractControl = getControlForIssue(form, issue, pathPrefix);
 
   control.setErrors({ [issue.messageCode]: issue });
   control.markAsTouched();
 }
 
-export function getControlForIssue(
-  form: UntypedFormGroup,
-  issue: Issue,
-  pathPrefix?: string,
-): AbstractControl {
+export function getControlForIssue(form: UntypedFormGroup, issue: Issue, pathPrefix?: string): AbstractControl {
   const fieldPath: string = getFieldPath(issue.field, pathPrefix);
 
   let curControl: AbstractControl = form;
-  fieldPath
-    .split('.')
-    .forEach((field) => (curControl = (<UntypedFormGroup>curControl).controls[field]));
+  fieldPath.split('.').forEach((field) => (curControl = (<UntypedFormGroup>curControl).controls[field]));
 
   return curControl;
 }
@@ -66,9 +56,7 @@ export function getMessageForIssue(label: string, issue: Issue): string {
   }
 
   msg = replacePlaceholder(msg, 'field', label);
-  issue.parameters.forEach(
-    (param: IssueParam) => (msg = replacePlaceholder(msg, param.name, param.value)),
-  );
+  issue.parameters.forEach((param: IssueParam) => (msg = replacePlaceholder(msg, param.name, param.value)));
   return msg;
 }
 
@@ -84,11 +72,7 @@ export function getMessageCode(apiError: ApiError): string {
   return apiError.issues[0].messageCode;
 }
 
-export function setInvalidParamValidationError(
-  form: UntypedFormGroup,
-  invalidParam: InvalidParam,
-  pathPrefix?: string,
-): void {
+export function setInvalidParamValidationError(form: UntypedFormGroup, invalidParam: InvalidParam, pathPrefix?: string): void {
   const control: AbstractControl = getControlForInvalidParam(form, invalidParam, pathPrefix);
 
   control.setErrors({ [invalidParam.reason]: invalidParam });
@@ -112,17 +96,20 @@ export function getMessageForInvalidParam(label: string, invalidParam: InvalidPa
   }
 
   msg = replacePlaceholder(msg, 'field', label);
-  invalidParam.constraintParameters.forEach(
-    (param: IssueParam) => (msg = replacePlaceholder(msg, param.name, param.value)),
-  );
+  invalidParam.constraintParameters.forEach((param: IssueParam) => (msg = replacePlaceholder(msg, param.name, param.value)));
   return msg;
 }
 
 export function getFieldPath(name: string, pathPrefix: string): string {
+  const path: string = _mapFormArrayElementNameToPath(name);
   if (isEmpty(pathPrefix)) {
-    return name.split('.').pop();
+    return path;
   }
 
-  const indexOfField = name.lastIndexOf(pathPrefix) + pathPrefix.length + 1;
-  return name.slice(indexOfField);
+  const indexOfField = path.lastIndexOf(pathPrefix) + pathPrefix.length + 1;
+  return path.slice(indexOfField);
+}
+
+export function _mapFormArrayElementNameToPath(name: string): string {
+  return name.replace(/\[(\d+?)]\./g, '.$1.');
 }
-- 
GitLab


From 7dfc1354ac3cea6d1fa9519969cb1d897e7a514c Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 18 Mar 2025 17:13:24 +0100
Subject: [PATCH 13/47] OZG-7473 load list resource

---
 .../statistik-fields-form-page.component.html |  2 +-
 ...atistik-fields-form-page.component.spec.ts | 15 +++----
 .../statistik-fields-form-page.component.ts   |  5 +--
 .../src/lib/aggregation-mapping.service.ts    |  2 +-
 alfa-client/libs/admin/statistik/src/index.ts |  1 +
 ...tion-mapping-form-container.component.html |  3 ++
 ...n-mapping-form-container.component.spec.ts | 40 +++++++++++++++++++
 ...gation-mapping-form-container.component.ts | 20 ++++++++++
 .../statistik-container.component.spec.ts     | 17 +++-----
 .../statistik-container.component.ts          |  1 -
 10 files changed, 79 insertions(+), 27 deletions(-)
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
 create mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts

diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.html b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.html
index a2e1b29bb9..d51d31da05 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.html
+++ b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.html
@@ -1 +1 @@
-<admin-statistik-fields-form data-test-id="evaluate-fields-form"></admin-statistik-fields-form>
\ No newline at end of file
+<admin-aggregation-mapping-form-container></admin-aggregation-mapping-form-container>
\ No newline at end of file
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
index 5805a079fa..7101165d69 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
@@ -1,19 +1,16 @@
-import { StatistikFieldsFormComponent } from '@admin-client/statistik';
-import { existsAsHtmlElement } from '@alfa-client/test-utils';
+import { AggregationMappingFormContainerComponent } from '@admin-client/statistik';
+import { expectComponentExistsInTemplate } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
-import { getDataTestIdOf } from '../../../../../../libs/tech-shared/test/data-test';
 import { StatistikFieldsFormPageComponent } from './statistik-fields-form-page.component';
 
 describe('StatistikFieldsFormPageComponent', () => {
   let component: StatistikFieldsFormPageComponent;
   let fixture: ComponentFixture<StatistikFieldsFormPageComponent>;
 
-  const evaluateFieldsForm: string = getDataTestIdOf('evaluate-fields-form');
-
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [StatistikFieldsFormPageComponent, MockComponent(StatistikFieldsFormComponent)],
+      imports: [StatistikFieldsFormPageComponent, MockComponent(AggregationMappingFormContainerComponent)],
     }).compileComponents();
 
     fixture = TestBed.createComponent(StatistikFieldsFormPageComponent);
@@ -26,11 +23,9 @@ describe('StatistikFieldsFormPageComponent', () => {
   });
 
   describe('template', () => {
-    describe('weiter felder auswerten form', () => {
+    describe('aggregation mapping form', () => {
       it('should exists', () => {
-        fixture.detectChanges();
-
-        existsAsHtmlElement(fixture, evaluateFieldsForm);
+        expectComponentExistsInTemplate(fixture, AggregationMappingFormContainerComponent);
       });
     });
   });
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
index 3758d1cdae..638bba3a0a 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
@@ -1,11 +1,10 @@
-import { StatistikFieldsFormComponent } from '@admin-client/statistik';
-import { CommonModule } from '@angular/common';
+import { AggregationMappingFormContainerComponent } from '@admin-client/statistik';
 import { Component } from '@angular/core';
 
 @Component({
   selector: 'statistik-fields-form-page',
   standalone: true,
-  imports: [CommonModule, StatistikFieldsFormComponent],
+  imports: [AggregationMappingFormContainerComponent],
   templateUrl: './statistik-fields-form-page.component.html',
 })
 export class StatistikFieldsFormPageComponent {}
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
index 19c85af76c..333d530998 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
@@ -5,7 +5,7 @@ import { AggregationMappingListResourceService } from './aggregation-mapping-lis
 import { AggregationMappingResourceService } from './aggregation-mapping-resource.service';
 import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
 
-@Injectable()
+@Injectable({ providedIn: 'root' })
 export class AggregationMappingService {
   private readonly listService = inject(AggregationMappingListResourceService);
   private readonly resourceService = inject(AggregationMappingResourceService);
diff --git a/alfa-client/libs/admin/statistik/src/index.ts b/alfa-client/libs/admin/statistik/src/index.ts
index 5b433fe321..c2e36a7669 100644
--- a/alfa-client/libs/admin/statistik/src/index.ts
+++ b/alfa-client/libs/admin/statistik/src/index.ts
@@ -1,2 +1,3 @@
+export * from './lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component';
 export * from './lib/statistik-container/statistik-container.component';
 export * from './lib/statistik-fields-form/statistik-fields-form.component';
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
new file mode 100644
index 0000000000..e6db36aca8
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
@@ -0,0 +1,3 @@
+<ods-spinner [stateResource]="listStateResource$ | async">
+  <admin-statistik-fields-form data-test-id="evaluate-fields-form"></admin-statistik-fields-form>
+</ods-spinner>
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
new file mode 100644
index 0000000000..311fc93977
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
@@ -0,0 +1,40 @@
+import { AggregationMappingService } from '@admin-client/reporting-shared';
+import { StatistikFieldsFormComponent } from '@admin-client/statistik';
+import { Mock, mock } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { SpinnerComponent } from '@ods/component';
+import { MockComponent } from 'ng-mocks';
+import { AggregationMappingFormContainerComponent } from './aggregation-mapping-form-container.component';
+
+describe('AggregationMappingFormContainerComponent', () => {
+  let component: AggregationMappingFormContainerComponent;
+  let fixture: ComponentFixture<AggregationMappingFormContainerComponent>;
+
+  let aggregationMappingService: Mock<AggregationMappingService>;
+
+  beforeEach(async () => {
+    aggregationMappingService = mock(AggregationMappingService);
+
+    await TestBed.configureTestingModule({
+      imports: [
+        AggregationMappingFormContainerComponent,
+        MockComponent(SpinnerComponent),
+        MockComponent(StatistikFieldsFormComponent),
+      ],
+      providers: [
+        {
+          provide: AggregationMappingService,
+          useValue: aggregationMappingService,
+        },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AggregationMappingFormContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
new file mode 100644
index 0000000000..21de73378a
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
@@ -0,0 +1,20 @@
+import { AggregationMappingListResource, AggregationMappingService } from '@admin-client/reporting-shared';
+import { StateResource } from '@alfa-client/tech-shared';
+import { AsyncPipe } from '@angular/common';
+import { Component, inject } from '@angular/core';
+import { SpinnerComponent } from '@ods/component';
+import { Observable } from 'rxjs';
+import { StatistikFieldsFormComponent } from '../statistik-fields-form/statistik-fields-form.component';
+
+@Component({
+  selector: 'admin-aggregation-mapping-form-container',
+  standalone: true,
+  imports: [SpinnerComponent, AsyncPipe, StatistikFieldsFormComponent],
+  templateUrl: './aggregation-mapping-form-container.component.html',
+})
+export class AggregationMappingFormContainerComponent {
+  public readonly aggregationMappingService = inject(AggregationMappingService);
+
+  public readonly listStateResource$: Observable<StateResource<AggregationMappingListResource>> =
+    this.aggregationMappingService.getList();
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
index 146cfa8b5c..7407e0c895 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
@@ -49,18 +49,13 @@ describe('StatistikContainerComponent', () => {
         MockComponent(RoutingButtonComponent),
         MockComponent(AggregationMappingListComponent),
       ],
-    })
-      .overrideComponent(StatistikContainerComponent, {
-        set: {
-          providers: [
-            {
-              provide: AggregationMappingService,
-              useValue: aggregationMappingService,
-            },
-          ],
+      providers: [
+        {
+          provide: AggregationMappingService,
+          useValue: aggregationMappingService,
         },
-      })
-      .compileComponents();
+      ],
+    }).compileComponents();
 
     fixture = TestBed.createComponent(StatistikContainerComponent);
     component = fixture.componentInstance;
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
index 00226c7c85..6465487752 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
@@ -35,7 +35,6 @@ import { AggregationMappingListComponent } from '../aggregation-mapping-list/agg
   templateUrl: './statistik-container.component.html',
   standalone: true,
   imports: [CommonModule, RoutingButtonComponent, AggregationMappingListComponent],
-  providers: [AggregationMappingService],
 })
 export class StatistikContainerComponent implements OnInit, OnDestroy {
   private service = inject(AggregationMappingService);
-- 
GitLab


From 45029c64ce44aea2e36ab1f8f9941e8aea3516cc Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 18 Mar 2025 17:20:50 +0100
Subject: [PATCH 14/47] OZG-7473 reload list

---
 ...gregation-mapping-form-container.component.spec.ts | 11 +++++++++++
 .../aggregation-mapping-form-container.component.ts   |  8 ++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
index 311fc93977..2f8fc1a4d7 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
@@ -2,6 +2,7 @@ import { AggregationMappingService } from '@admin-client/reporting-shared';
 import { StatistikFieldsFormComponent } from '@admin-client/statistik';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
 import { SpinnerComponent } from '@ods/component';
 import { MockComponent } from 'ng-mocks';
 import { AggregationMappingFormContainerComponent } from './aggregation-mapping-form-container.component';
@@ -37,4 +38,14 @@ describe('AggregationMappingFormContainerComponent', () => {
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('component', () => {
+    describe('on destroy', () => {
+      it('should reload list', () => {
+        component.ngOnDestroy();
+
+        expect(aggregationMappingService.refreshList).toHaveBeenCalled();
+      });
+    });
+  });
 });
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
index 21de73378a..31b284ec01 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
@@ -1,7 +1,7 @@
 import { AggregationMappingListResource, AggregationMappingService } from '@admin-client/reporting-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { AsyncPipe } from '@angular/common';
-import { Component, inject } from '@angular/core';
+import { Component, inject, OnDestroy } from '@angular/core';
 import { SpinnerComponent } from '@ods/component';
 import { Observable } from 'rxjs';
 import { StatistikFieldsFormComponent } from '../statistik-fields-form/statistik-fields-form.component';
@@ -12,9 +12,13 @@ import { StatistikFieldsFormComponent } from '../statistik-fields-form/statistik
   imports: [SpinnerComponent, AsyncPipe, StatistikFieldsFormComponent],
   templateUrl: './aggregation-mapping-form-container.component.html',
 })
-export class AggregationMappingFormContainerComponent {
+export class AggregationMappingFormContainerComponent implements OnDestroy {
   public readonly aggregationMappingService = inject(AggregationMappingService);
 
   public readonly listStateResource$: Observable<StateResource<AggregationMappingListResource>> =
     this.aggregationMappingService.getList();
+
+  ngOnDestroy(): void {
+    this.aggregationMappingService.refreshList();
+  }
 }
-- 
GitLab


From 8d29bfd69f3aaf768fb1068e845dcd939f2b6598 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Wed, 19 Mar 2025 20:52:20 +0100
Subject: [PATCH 15/47] OZG-73743 rename statistik to aggregation-mapping

---
 ...aggregation-mapping-form.e2e.component.ts} |  2 +-
 .../aggregation-mapping.e2e.component.ts}     |  4 +-
 .../aggregation-mapping.cy.ts}                | 14 +++---
 alfa-client/apps/admin/src/app/app.routes.ts  | 10 ++--
 ...regation-mapping-form-page.component.html} |  0
 ...ation-mapping-form-page.component.spec.ts} | 14 +++---
 ...ggregation-mapping-form-page.component.ts} |  8 ++--
 ...regation-mapping-list-page.component.html} |  2 +-
 ...ation-mapping-list-page.component.spec.ts} | 15 +++---
 ...ggregation-mapping-list-page.component.ts} | 10 ++--
 .../.eslintrc.json                            |  0
 .../libs/admin/aggregation-mapping/README.md  |  1 +
 .../jest.config.ts                            |  4 +-
 .../project.json                              |  8 ++--
 .../admin/aggregation-mapping/src/index.ts    |  2 +
 ...tion-mapping-form-container.component.html |  3 ++
 ...n-mapping-form-container.component.spec.ts |  6 +--
 ...gation-mapping-form-container.component.ts |  4 +-
 ...egation-mapping-field-form.component.html} |  2 +-
 ...tion-mapping-field-form.component.spec.ts} | 30 ++++++------
 ...gregation-mapping-field-form.component.ts} | 12 ++---
 ...ion-mapping-field-list-form.component.html | 10 ++++
 ...mapping-field-list-form.component.spec.ts} | 38 ++++++++-------
 ...ation-mapping-field-list-form.component.ts | 20 ++++++++
 .../aggregation-mapping-form.component.html}  | 16 +++----
 ...ggregation-mapping-form.component.spec.ts} | 46 +++++++++----------
 .../aggregation-mapping-form.component.ts}    | 18 ++++----
 .../aggregation-mapping-form.service.ts}      | 20 ++++----
 .../aggregation-mapping.formservice.spec.ts}  | 34 +++++++-------
 ...ion-mapping-list-container.component.html} |  2 +-
 ...-mapping-list-container.component.spec.ts} | 14 +++---
 ...ation-mapping-list-container.component.ts} |  8 ++--
 ...gregation-mapping-list-item.component.html |  0
 ...gation-mapping-list-item.component.spec.ts |  2 +-
 ...aggregation-mapping-list-item.component.ts |  0
 .../aggregation-mapping-list.component.html   |  0
 ...aggregation-mapping-list.component.spec.ts |  4 +-
 .../aggregation-mapping-list.component.ts     |  2 +-
 .../src/test-setup.ts                         |  0
 .../tsconfig.json                             |  0
 .../tsconfig.lib.json                         |  0
 .../tsconfig.spec.json                        |  0
 alfa-client/libs/admin/statistik/README.md    |  7 ---
 alfa-client/libs/admin/statistik/src/index.ts |  3 --
 ...tion-mapping-form-container.component.html |  3 --
 ...tistik-fields-mappings-form.component.html | 10 ----
 ...tatistik-fields-mappings-form.component.ts | 20 --------
 alfa-client/tsconfig.base.json                |  2 +-
 48 files changed, 212 insertions(+), 218 deletions(-)
 rename alfa-client/apps/admin-e2e/src/components/{statistik/statistik-fields-form.e2e.component.ts => aggregation-mapping/aggregation-mapping-form.e2e.component.ts} (97%)
 rename alfa-client/apps/admin-e2e/src/components/{statistik/statistik.e2e.component.ts => aggregation-mapping/aggregation-mapping.e2e.component.ts} (73%)
 rename alfa-client/apps/admin-e2e/src/e2e/main-tests/{statistik/statistik-fields.cy.ts => aggregation-mapping/aggregation-mapping.cy.ts} (70%)
 rename alfa-client/apps/admin/src/pages/{statistik/statistik-fields-form-page/statistik-fields-form-page.component.html => aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.html} (100%)
 rename alfa-client/apps/admin/src/pages/{statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts => aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.spec.ts} (59%)
 rename alfa-client/apps/admin/src/pages/{statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts => aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.ts} (50%)
 rename alfa-client/apps/admin/src/pages/{statistik/statistik-page/statistik-page.component.html => aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.html} (91%)
 rename alfa-client/apps/admin/src/pages/{statistik/statistik-page/statistik-page.component.spec.ts => aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.spec.ts} (70%)
 rename alfa-client/apps/admin/src/pages/{statistik/statistik-page/statistik-page.component.ts => aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.ts} (76%)
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/.eslintrc.json (100%)
 create mode 100644 alfa-client/libs/admin/aggregation-mapping/README.md
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/jest.config.ts (83%)
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/project.json (62%)
 create mode 100644 alfa-client/libs/admin/aggregation-mapping/src/index.ts
 create mode 100644 alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts (85%)
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts (82%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html} (95%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts} (70%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts} (52%)
 create mode 100644 alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts} (51%)
 create mode 100644 alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html} (68%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts} (69%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts} (59%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.service.ts} (71%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts => aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts} (77%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-container/statistik-container.component.html => aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.html} (93%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-container/statistik-container.component.spec.ts => aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts} (87%)
 rename alfa-client/libs/admin/{statistik/src/lib/statistik-container/statistik-container.component.ts => aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.ts} (84%)
 rename alfa-client/libs/admin/{statistik/src/lib => aggregation-mapping/src/lib/aggregation-mapping-list-container}/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html (100%)
 rename alfa-client/libs/admin/{statistik/src/lib => aggregation-mapping/src/lib/aggregation-mapping-list-container}/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts (93%)
 rename alfa-client/libs/admin/{statistik/src/lib => aggregation-mapping/src/lib/aggregation-mapping-list-container}/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts (100%)
 rename alfa-client/libs/admin/{statistik/src/lib => aggregation-mapping/src/lib/aggregation-mapping-list-container}/aggregation-mapping-list/aggregation-mapping-list.component.html (100%)
 rename alfa-client/libs/admin/{statistik/src/lib => aggregation-mapping/src/lib/aggregation-mapping-list-container}/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts (96%)
 rename alfa-client/libs/admin/{statistik/src/lib => aggregation-mapping/src/lib/aggregation-mapping-list-container}/aggregation-mapping-list/aggregation-mapping-list.component.ts (92%)
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/src/test-setup.ts (100%)
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/tsconfig.json (100%)
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/tsconfig.lib.json (100%)
 rename alfa-client/libs/admin/{statistik => aggregation-mapping}/tsconfig.spec.json (100%)
 delete mode 100644 alfa-client/libs/admin/statistik/README.md
 delete mode 100644 alfa-client/libs/admin/statistik/src/index.ts
 delete mode 100644 alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
 delete mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html
 delete mode 100644 alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts

diff --git a/alfa-client/apps/admin-e2e/src/components/statistik/statistik-fields-form.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
similarity index 97%
rename from alfa-client/apps/admin-e2e/src/components/statistik/statistik-fields-form.e2e.component.ts
rename to alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
index 8936e02edb..112cc9e0aa 100644
--- a/alfa-client/apps/admin-e2e/src/components/statistik/statistik-fields-form.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
@@ -1,6 +1,6 @@
 import { enterWith } from '../../support/cypress.util';
 
-export class StatistikFieldsFormE2EComponent {
+export class AggregationMappingFormE2EComponent {
   private readonly formEngineInput: string = 'form-engine-name-text-input';
   private readonly formIdInput: string = 'form-id-text-input';
   private readonly formDataFieldInput: string = 'mapping-field-';
diff --git a/alfa-client/apps/admin-e2e/src/components/statistik/statistik.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
similarity index 73%
rename from alfa-client/apps/admin-e2e/src/components/statistik/statistik.e2e.component.ts
rename to alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
index b7467232f5..8e9ad4a76d 100644
--- a/alfa-client/apps/admin-e2e/src/components/statistik/statistik.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
@@ -1,5 +1,5 @@
-export class StatistikE2EComponent {
-  private readonly locatorHeaderText: string = 'statistik-header-text';
+export class AggregationMappingE2EComponent {
+  private readonly locatorHeaderText: string = 'aggregation-mapping-header-text';
   private readonly locatorWeitereFelderAuswertenButton = 'weitere-felder-auswerten-button';
 
   public getHeaderText(): Cypress.Chainable<Element> {
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/statistik/statistik-fields.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
similarity index 70%
rename from alfa-client/apps/admin-e2e/src/e2e/main-tests/statistik/statistik-fields.cy.ts
rename to alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
index d877ae4b90..91ed35a2dd 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/statistik/statistik-fields.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
@@ -1,11 +1,11 @@
-import { StatistikE2EComponent } from 'apps/admin-e2e/src/components/statistik/statistik.e2e.component';
-import { StatistikFieldsFormE2EComponent } from '../../../components/statistik/statistik-fields-form.e2e.component';
-import { exist, haveText, haveValue } from '../../../support/cypress.util';
+import { AggregationMappingFormE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping-form.e2e.component';
+import { AggregationMappingE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping.e2e.component';
+import { exist, haveValue } from '../../../support/cypress.util';
 import { loginAsDaria } from '../../../support/user-util';
 
-describe('Felder in Statistik hinzufügen', () => {
-  const component: StatistikE2EComponent = new StatistikE2EComponent();
-  const fieldsFormComponent: StatistikFieldsFormE2EComponent = new StatistikFieldsFormE2EComponent();
+describe('Aggregation Mapping hinzufügen', () => {
+  const component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
+  const fieldsFormComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
 
   const dataText1: string = 'Eingabe A';
   const dataText2: string = 'Eingabe B';
@@ -49,7 +49,7 @@ describe('Felder in Statistik hinzufügen', () => {
     haveValue(fieldsFormComponent.getDataFieldInput(0), dataText2);
   });
 
-  it('should navigate to statistik on cancel', () => {
+  it('should navigate to aggregation mapping on cancel', () => {
     fieldsFormComponent.cancel();
 
     exist(component.getWeitereFelderAuswertenButton());
diff --git a/alfa-client/apps/admin/src/app/app.routes.ts b/alfa-client/apps/admin/src/app/app.routes.ts
index 2d21b25201..25576ae40b 100644
--- a/alfa-client/apps/admin/src/app/app.routes.ts
+++ b/alfa-client/apps/admin/src/app/app.routes.ts
@@ -26,10 +26,10 @@ import { ROUTES } from '@admin-client/shared';
 import { UserFormComponent } from '@admin-client/user';
 import { ApiRootLinkRel } from '@alfa-client/api-root-shared';
 import { Route } from '@angular/router';
+import { AggregationMappingFormPageComponent } from '../pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component';
+import { AggregationMappingListPageComponent } from '../pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component';
 import { OrganisationsEinheitPageComponent } from '../pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component';
 import { PostfachPageComponent } from '../pages/postfach/postfach-page/postfach-page.component';
-import { StatistikFieldsFormPageComponent } from '../pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component';
-import { StatistikPageComponent } from '../pages/statistik/statistik-page/statistik-page.component';
 import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component';
 import { UserFormPageComponent } from '../pages/user/user-form-page/user-form-page.component';
 import { UserListPageComponent } from '../pages/user/user-list-page/user-list-page.component';
@@ -84,7 +84,7 @@ export const appRoutes: Route[] = [
   },
   {
     path: ROUTES.AGGREGATION_MAPPING,
-    component: StatistikPageComponent,
+    component: AggregationMappingListPageComponent,
     title: 'Admin | Statistik',
     runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
@@ -92,7 +92,7 @@ export const appRoutes: Route[] = [
   },
   {
     path: ROUTES.AGGREGATION_MAPPING_NEU,
-    component: StatistikFieldsFormPageComponent,
+    component: AggregationMappingFormPageComponent,
     title: 'Admin | Statistik weitere Felder auswerten',
     runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
@@ -100,7 +100,7 @@ export const appRoutes: Route[] = [
   },
   {
     path: ROUTES.AGGREGATION_MAPPING_ID,
-    component: StatistikFieldsFormPageComponent,
+    component: AggregationMappingFormPageComponent,
     title: 'Admin | Statistik weitere Felder auswerten',
     runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.html b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.html
similarity index 100%
rename from alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.html
rename to alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.html
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.spec.ts
similarity index 59%
rename from alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
rename to alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.spec.ts
index 7101165d69..f8d31cfc83 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.spec.ts
@@ -1,19 +1,19 @@
-import { AggregationMappingFormContainerComponent } from '@admin-client/statistik';
+import { AggregationMappingFormContainerComponent } from '@admin-client/aggregation-mapping';
 import { expectComponentExistsInTemplate } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
-import { StatistikFieldsFormPageComponent } from './statistik-fields-form-page.component';
+import { AggregationMappingFormPageComponent } from './aggregation-mapping-form-page.component';
 
-describe('StatistikFieldsFormPageComponent', () => {
-  let component: StatistikFieldsFormPageComponent;
-  let fixture: ComponentFixture<StatistikFieldsFormPageComponent>;
+describe('AggregationMappingFormPageComponent', () => {
+  let component: AggregationMappingFormPageComponent;
+  let fixture: ComponentFixture<AggregationMappingFormPageComponent>;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [StatistikFieldsFormPageComponent, MockComponent(AggregationMappingFormContainerComponent)],
+      imports: [AggregationMappingFormPageComponent, MockComponent(AggregationMappingFormContainerComponent)],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(StatistikFieldsFormPageComponent);
+    fixture = TestBed.createComponent(AggregationMappingFormPageComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.ts
similarity index 50%
rename from alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
rename to alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.ts
index 638bba3a0a..a85688c8b2 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-form-page/aggregation-mapping-form-page.component.ts
@@ -1,10 +1,10 @@
-import { AggregationMappingFormContainerComponent } from '@admin-client/statistik';
+import { AggregationMappingFormContainerComponent } from '@admin-client/aggregation-mapping';
 import { Component } from '@angular/core';
 
 @Component({
-  selector: 'statistik-fields-form-page',
+  selector: 'admin-aggregation-mapping-form-page',
   standalone: true,
   imports: [AggregationMappingFormContainerComponent],
-  templateUrl: './statistik-fields-form-page.component.html',
+  templateUrl: './aggregation-mapping-form-page.component.html',
 })
-export class StatistikFieldsFormPageComponent {}
+export class AggregationMappingFormPageComponent {}
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.html b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.html
similarity index 91%
rename from alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.html
rename to alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.html
index 5213f51259..ac183ce76a 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.html
+++ b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.html
@@ -23,4 +23,4 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<admin-statistik-container data-test-id="statistik-container" />
+<admin-aggregation-mapping-list-container data-test-id="aggregation-mapping-container" />
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.spec.ts b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.spec.ts
similarity index 70%
rename from alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.spec.ts
rename to alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.spec.ts
index 2166339888..b036d9be9e 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.spec.ts
@@ -21,24 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StatistikContainerComponent } from '@admin-client/statistik';
+import { AggregationMappingListContainerComponent } from '@admin-client/aggregation-mapping';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
-import { StatistikPageComponent } from './statistik-page.component';
+import { AggregationMappingListPageComponent } from './aggregation-mapping-list-page.component';
 
-describe('StatistikPageComponent', () => {
-  let component: StatistikPageComponent;
-  let fixture: ComponentFixture<StatistikPageComponent>;
+describe('AggregationMappingListPageComponent', () => {
+  let component: AggregationMappingListPageComponent;
+  let fixture: ComponentFixture<AggregationMappingListPageComponent>;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [],
-      declarations: [StatistikPageComponent, MockComponent(StatistikContainerComponent)],
+      imports: [AggregationMappingListPageComponent, MockComponent(AggregationMappingListContainerComponent)],
     }).compileComponents();
   });
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(StatistikPageComponent);
+    fixture = TestBed.createComponent(AggregationMappingListPageComponent);
     component = fixture.componentInstance;
 
     fixture.detectChanges();
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.ts b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.ts
similarity index 76%
rename from alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.ts
rename to alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.ts
index 53fd00fc7c..47858d2978 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-page/statistik-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/aggregation-mapping/aggregation-mapping-list-page/aggregation-mapping-list-page.component.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StatistikContainerComponent } from '@admin-client/statistik';
+import { AggregationMappingListContainerComponent } from '@admin-client/aggregation-mapping';
 import { Component } from '@angular/core';
 
 @Component({
-  selector: 'statistik-page',
+  selector: 'admin-aggregation-mapping-list-page',
   standalone: true,
-  imports: [StatistikContainerComponent],
-  templateUrl: './statistik-page.component.html',
+  imports: [AggregationMappingListContainerComponent],
+  templateUrl: './aggregation-mapping-list-page.component.html',
 })
-export class StatistikPageComponent {}
+export class AggregationMappingListPageComponent {}
diff --git a/alfa-client/libs/admin/statistik/.eslintrc.json b/alfa-client/libs/admin/aggregation-mapping/.eslintrc.json
similarity index 100%
rename from alfa-client/libs/admin/statistik/.eslintrc.json
rename to alfa-client/libs/admin/aggregation-mapping/.eslintrc.json
diff --git a/alfa-client/libs/admin/aggregation-mapping/README.md b/alfa-client/libs/admin/aggregation-mapping/README.md
new file mode 100644
index 0000000000..4e7c28147d
--- /dev/null
+++ b/alfa-client/libs/admin/aggregation-mapping/README.md
@@ -0,0 +1 @@
+# Aggregation Mapping
\ No newline at end of file
diff --git a/alfa-client/libs/admin/statistik/jest.config.ts b/alfa-client/libs/admin/aggregation-mapping/jest.config.ts
similarity index 83%
rename from alfa-client/libs/admin/statistik/jest.config.ts
rename to alfa-client/libs/admin/aggregation-mapping/jest.config.ts
index fc41bd8816..8ae2a4a3db 100644
--- a/alfa-client/libs/admin/statistik/jest.config.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/jest.config.ts
@@ -1,8 +1,8 @@
 export default {
-  displayName: 'admin-statistik',
+  displayName: 'admin-aggregation-mapping',
   preset: '../../../jest.preset.js',
   setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
-  coverageDirectory: '../../../coverage/libs/admin/statistik',
+  coverageDirectory: '../../../coverage/libs/admin/aggregation-mapping',
   transform: {
     '^.+\\.(ts|mjs|js|html)$': [
       'jest-preset-angular',
diff --git a/alfa-client/libs/admin/statistik/project.json b/alfa-client/libs/admin/aggregation-mapping/project.json
similarity index 62%
rename from alfa-client/libs/admin/statistik/project.json
rename to alfa-client/libs/admin/aggregation-mapping/project.json
index a5c36fc013..ab4704d303 100644
--- a/alfa-client/libs/admin/statistik/project.json
+++ b/alfa-client/libs/admin/aggregation-mapping/project.json
@@ -1,7 +1,7 @@
 {
-  "name": "admin-statistik",
+  "name": "admin-aggregation-mapping",
   "$schema": "../../../node_modules/nx/schemas/project-schema.json",
-  "sourceRoot": "libs/admin/statistik/src",
+  "sourceRoot": "libs/admin/aggregation-mapping/src",
   "prefix": "admin",
   "projectType": "library",
   "tags": [],
@@ -10,8 +10,8 @@
       "executor": "@nx/jest:jest",
       "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
       "options": {
-        "tsConfig": "libs/admin/statistik/tsconfig.lib.json",
-        "jestConfig": "libs/admin/statistik/jest.config.ts"
+        "tsConfig": "libs/admin/aggregation-mapping/tsconfig.lib.json",
+        "jestConfig": "libs/admin/aggregation-mapping/jest.config.ts"
       }
     },
     "lint": {
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/index.ts b/alfa-client/libs/admin/aggregation-mapping/src/index.ts
new file mode 100644
index 0000000000..aa299f4458
--- /dev/null
+++ b/alfa-client/libs/admin/aggregation-mapping/src/index.ts
@@ -0,0 +1,2 @@
+export * from './lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component';
+export * from './lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component';
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
new file mode 100644
index 0000000000..ac4fc2d0cc
--- /dev/null
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
@@ -0,0 +1,3 @@
+<ods-spinner [stateResource]="listStateResource$ | async">
+  <admin-aggregation-mapping-form data-test-id="evaluate-fields-form"></admin-aggregation-mapping-form>
+</ods-spinner>
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
similarity index 85%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
index 2f8fc1a4d7..d192a6d428 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.spec.ts
@@ -1,11 +1,11 @@
+import { AggregationMappingFormContainerComponent } from '@admin-client/aggregation-mapping';
 import { AggregationMappingService } from '@admin-client/reporting-shared';
-import { StatistikFieldsFormComponent } from '@admin-client/statistik';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { expect } from '@jest/globals';
 import { SpinnerComponent } from '@ods/component';
 import { MockComponent } from 'ng-mocks';
-import { AggregationMappingFormContainerComponent } from './aggregation-mapping-form-container.component';
+import { AggregationMappingFormComponent } from './aggregation-mapping-form/aggregation-mapping-form.component';
 
 describe('AggregationMappingFormContainerComponent', () => {
   let component: AggregationMappingFormContainerComponent;
@@ -20,7 +20,7 @@ describe('AggregationMappingFormContainerComponent', () => {
       imports: [
         AggregationMappingFormContainerComponent,
         MockComponent(SpinnerComponent),
-        MockComponent(StatistikFieldsFormComponent),
+        MockComponent(AggregationMappingFormComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
similarity index 82%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
index 31b284ec01..f20feab09a 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.ts
@@ -4,12 +4,12 @@ import { AsyncPipe } from '@angular/common';
 import { Component, inject, OnDestroy } from '@angular/core';
 import { SpinnerComponent } from '@ods/component';
 import { Observable } from 'rxjs';
-import { StatistikFieldsFormComponent } from '../statistik-fields-form/statistik-fields-form.component';
+import { AggregationMappingFormComponent } from './aggregation-mapping-form/aggregation-mapping-form.component';
 
 @Component({
   selector: 'admin-aggregation-mapping-form-container',
   standalone: true,
-  imports: [SpinnerComponent, AsyncPipe, StatistikFieldsFormComponent],
+  imports: [SpinnerComponent, AsyncPipe, AggregationMappingFormComponent],
   templateUrl: './aggregation-mapping-form-container.component.html',
 })
 export class AggregationMappingFormContainerComponent implements OnDestroy {
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
similarity index 95%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
index 05dd38f408..c5f184738c 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
@@ -1,5 +1,5 @@
 <form [formGroup]="formService.form">
-  <ng-container [formArrayName]="StatistikFieldsFormService.FIELD_MAPPINGS">
+  <ng-container [formArrayName]="AggregationMappingFormService.FIELD_MAPPINGS">
     <ng-container [formGroupName]="index">
       <div class="flex w-full flex-col gap-2 mt-4 bg-gray-100 p-4 rounded-md">
         <div class="flex flex-row items-center justify-between">
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
similarity index 70%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
index ff1cd734ac..cd207241e7 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
@@ -7,13 +7,13 @@ import { expect } from '@jest/globals';
 import { TextEditorComponent } from '@ods/component';
 import { ButtonComponent, DeleteIconComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
-import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
-import { StatistikFieldsFormService } from '../../statistik-fields.formservice';
-import { StatistikFieldMappingFormComponent } from './statistik-field-mapping-form.component';
+import { getDataTestIdOf } from '../../../../../../../../tech-shared/test/data-test';
+import { AggregationMappingFormService } from '../../aggregation-mapping-form.service';
+import { AggregationMappingFieldFormComponent } from './aggregation-mapping-field-form.component';
 
-describe('AdminStatistikFieldMappingFormComponent', () => {
-  let component: StatistikFieldMappingFormComponent;
-  let fixture: ComponentFixture<StatistikFieldMappingFormComponent>;
+describe('AggregationMappingFieldFormComponent', () => {
+  let component: AggregationMappingFieldFormComponent;
+  let fixture: ComponentFixture<AggregationMappingFieldFormComponent>;
 
   const formBuilder: FormBuilder = new FormBuilder();
   const fieldIndex: number = 0;
@@ -21,20 +21,20 @@ describe('AdminStatistikFieldMappingFormComponent', () => {
   const targetPathEditorTestId: string = getDataTestIdOf('target-mapping-field-0');
   const removeMappingButtonTestId: string = getDataTestIdOf('remove-mapping-0');
 
-  let formService: Mock<StatistikFieldsFormService>;
+  let formService: Mock<AggregationMappingFormService>;
 
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
-      [StatistikFieldsFormService.FIELD_MAPPINGS]: formBuilder.array([
+      [AggregationMappingFormService.FIELD_MAPPINGS]: formBuilder.array([
         new FormGroup({
-          [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
-          [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
         }),
       ]),
     });
 
     formService = <any>{
-      ...mock(StatistikFieldsFormService),
+      ...mock(AggregationMappingFormService),
       form,
       addMapping: jest.fn(),
       removeMapping: jest.fn(),
@@ -42,13 +42,13 @@ describe('AdminStatistikFieldMappingFormComponent', () => {
 
     mockGetValue(
       formService,
-      StatistikFieldsFormService.FIELD_MAPPINGS,
-      form.controls[StatistikFieldsFormService.FIELD_MAPPINGS],
+      AggregationMappingFormService.FIELD_MAPPINGS,
+      form.controls[AggregationMappingFormService.FIELD_MAPPINGS],
     );
 
     await TestBed.configureTestingModule({
       imports: [
-        StatistikFieldMappingFormComponent,
+        AggregationMappingFieldFormComponent,
         MockComponent(TextEditorComponent),
         MockComponent(ButtonComponent),
         MockComponent(DeleteIconComponent),
@@ -61,7 +61,7 @@ describe('AdminStatistikFieldMappingFormComponent', () => {
       ],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(StatistikFieldMappingFormComponent);
+    fixture = TestBed.createComponent(AggregationMappingFieldFormComponent);
     component = fixture.componentInstance;
     component.index = fieldIndex;
     fixture.detectChanges();
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
similarity index 52%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
index 0789e17703..e80a74f035 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-field-mapping-form/statistik-field-mapping-form.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
@@ -3,18 +3,18 @@ import { Component, inject, Input } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { TextEditorComponent } from '@ods/component';
 import { ButtonComponent, DeleteIconComponent } from '@ods/system';
-import { StatistikFieldsFormService } from '../../statistik-fields.formservice';
+import { AggregationMappingFormService } from '../../aggregation-mapping-form.service';
 
 @Component({
-  selector: 'admin-statistik-field-mapping-form',
+  selector: 'admin-aggregatin-mapping-field-form',
   standalone: true,
-  templateUrl: './statistik-field-mapping-form.component.html',
+  templateUrl: './aggregation-mapping-field-form.component.html',
   imports: [ButtonComponent, DeleteIconComponent, ReactiveFormsModule, TextEditorComponent],
 })
-export class StatistikFieldMappingFormComponent {
+export class AggregationMappingFieldFormComponent {
   @Input({ required: true }) index: number;
 
-  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
+  public readonly formService = <AggregationMappingFormService>inject(ADMIN_FORMSERVICE);
 
-  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
+  public readonly AggregationMappingFormService = AggregationMappingFormService;
 }
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
new file mode 100644
index 0000000000..ee829b2a70
--- /dev/null
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
@@ -0,0 +1,10 @@
+<form [formGroup]="formService.form">
+  <div class="flex flex-col" [formArrayName]="AggregationMappingFormService.FIELD_MAPPINGS">
+    <div *ngFor="let ignore of mappingsFormArray; let i = index">
+      <admin-aggregatin-mapping-field-form
+        [index]="i"
+        [attr.data-test-id]="'aggregation-mapping-field-mapping-form-' + i"
+      ></admin-aggregatin-mapping-field-form>
+    </div>
+  </div>
+</form>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts
similarity index 51%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts
index 6470d91cfe..345f9cbf24 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts
@@ -6,32 +6,32 @@ import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angul
 import { expect } from '@jest/globals';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
-import { StatistikFieldsFormService } from '../statistik-fields.formservice';
-import { StatistikFieldMappingFormComponent } from './statistik-field-mapping-form/statistik-field-mapping-form.component';
-import { StatistikFieldsMappingsFormComponent } from './statistik-fields-mappings-form.component';
+import { AggregationMappingFormService } from '../aggregation-mapping-form.service';
+import { AggregationMappingFieldFormComponent } from './aggregation-mapping-field-form/aggregation-mapping-field-form.component';
+import { AggregationMappingFieldListFormComponent } from './aggregation-mapping-field-list-form.component';
 
-describe('StatistikFieldsFormMappingComponent', () => {
-  let component: StatistikFieldsMappingsFormComponent;
-  let fixture: ComponentFixture<StatistikFieldsMappingsFormComponent>;
+describe('AggregationMappingFieldListFormComponent', () => {
+  let component: AggregationMappingFieldListFormComponent;
+  let fixture: ComponentFixture<AggregationMappingFieldListFormComponent>;
 
-  const mappingForm: string = getDataTestIdOf('statistik-field-mapping-form-0');
+  const mappingForm: string = getDataTestIdOf('aggregation-mapping-field-mapping-form-0');
 
   const formBuilder: FormBuilder = new FormBuilder();
 
-  let formService: Mock<StatistikFieldsFormService>;
+  let formService: Mock<AggregationMappingFormService>;
 
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
-      [StatistikFieldsFormService.FIELD_MAPPINGS]: formBuilder.array([
+      [AggregationMappingFormService.FIELD_MAPPINGS]: formBuilder.array([
         new FormGroup({
-          [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
-          [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
         }),
       ]),
     });
 
     formService = <any>{
-      ...mock(StatistikFieldsFormService),
+      ...mock(AggregationMappingFormService),
       form,
       addMapping: jest.fn(),
       removeMapping: jest.fn(),
@@ -39,12 +39,16 @@ describe('StatistikFieldsFormMappingComponent', () => {
 
     mockGetValue(
       formService,
-      StatistikFieldsFormService.FIELD_MAPPINGS,
-      form.controls[StatistikFieldsFormService.FIELD_MAPPINGS],
+      AggregationMappingFormService.FIELD_MAPPINGS,
+      form.controls[AggregationMappingFormService.FIELD_MAPPINGS],
     );
 
     await TestBed.configureTestingModule({
-      imports: [ReactiveFormsModule, StatistikFieldsMappingsFormComponent, MockComponent(StatistikFieldMappingFormComponent)],
+      imports: [
+        ReactiveFormsModule,
+        AggregationMappingFieldListFormComponent,
+        MockComponent(AggregationMappingFieldFormComponent),
+      ],
       providers: [
         {
           provide: ADMIN_FORMSERVICE,
@@ -53,7 +57,7 @@ describe('StatistikFieldsFormMappingComponent', () => {
       ],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(StatistikFieldsMappingsFormComponent);
+    fixture = TestBed.createComponent(AggregationMappingFieldListFormComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
@@ -71,7 +75,7 @@ describe('StatistikFieldsFormMappingComponent', () => {
       });
 
       it('should have inputs', () => {
-        const mappingComponent: StatistikFieldMappingFormComponent = getElementComponentFromFixtureByCss(fixture, mappingForm);
+        const mappingComponent: AggregationMappingFieldFormComponent = getElementComponentFromFixtureByCss(fixture, mappingForm);
 
         expect(mappingComponent.index).toEqual(0);
       });
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts
new file mode 100644
index 0000000000..2adaffcbef
--- /dev/null
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts
@@ -0,0 +1,20 @@
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { CommonModule } from '@angular/common';
+import { Component, inject } from '@angular/core';
+import { AbstractControl, ReactiveFormsModule } from '@angular/forms';
+import { AggregationMappingFormService } from '../aggregation-mapping-form.service';
+import { AggregationMappingFieldFormComponent } from './aggregation-mapping-field-form/aggregation-mapping-field-form.component';
+
+@Component({
+  selector: 'admin-aggregation-mapping-field-list-form',
+  templateUrl: './aggregation-mapping-field-list-form.component.html',
+  standalone: true,
+  imports: [CommonModule, ReactiveFormsModule, AggregationMappingFieldFormComponent],
+})
+export class AggregationMappingFieldListFormComponent {
+  public readonly formService = <AggregationMappingFormService>inject(ADMIN_FORMSERVICE);
+
+  public readonly mappingsFormArray: AbstractControl[] = this.formService.mappings.controls;
+
+  public readonly AggregationMappingFormService = AggregationMappingFormService;
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
similarity index 68%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
index b9f078d75e..abcbef7402 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
@@ -1,19 +1,19 @@
-<h2 class="heading-2" data-test-id="statistik-fields-form-header-text">Felder zur Auswertung hinzufügen</h2>
+<h2 class="heading-2" data-test-id="aggregation-mapping-fields-form-header-text">Felder zur Auswertung hinzufügen</h2>
 
 <ods-spinner [stateResource]="aggregationMappingStateResource$ | async">
   <div class="flex max-w-4xl flex-col gap-4">
     <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-2">
       <ods-text-editor
-        [formControlName]="StatistikFieldsFormService.FIELD_NAME"
+        [formControlName]="AggregationMappingFormService.FIELD_NAME"
         label="Name"
         placeholder=""
         isRequired="true"
-        data-test-id="statistik-name-text-editor"
-        dataTestId="statistik-name"
+        data-test-id="aggregation-mapping-name-text-editor"
+        dataTestId="aggregation-mapping-name"
       ></ods-text-editor>
-      <div [formGroupName]="StatistikFieldsFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
+      <div [formGroupName]="AggregationMappingFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
         <ods-text-editor
-          [formControlName]="StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME"
+          [formControlName]="AggregationMappingFormService.FIELD_FORM_ENGINE_NAME"
           label="Formengine"
           placeholder="Tragen Sie hier die Formengine des Formulars ein."
           isRequired="true"
@@ -21,7 +21,7 @@
           dataTestId="form-engine-name"
         ></ods-text-editor>
         <ods-text-editor
-          [formControlName]="StatistikFieldsFormService.FIELD_FORM_ID"
+          [formControlName]="AggregationMappingFormService.FIELD_FORM_ID"
           label="FormID"
           placeholder="Tragen Sie hier die FormID des Formulars ein."
           isRequired="true"
@@ -29,7 +29,7 @@
           dataTestId="form-id"
         ></ods-text-editor>
       </div>
-      <admin-statistik-fields-form-mapping />
+      <admin-aggregation-mapping-field-list-form />
     </form>
     <ods-button
       text="Datenfeld hinzufügen"
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
similarity index 69%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
index 5dc2a0eafa..e6a2b6989c 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
@@ -1,5 +1,5 @@
 import { AggregationMappingResource } from '@admin-client/reporting-shared';
-import { ADMIN_FORMSERVICE, ROUTES } from '@admin-client/shared';
+import { ADMIN_FORMSERVICE, AdminCancelButtonComponent, AdminSaveButtonComponent, ROUTES } from '@admin-client/shared';
 import { createStateResource, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
 import {
   dispatchEventFromFixture,
@@ -16,18 +16,16 @@ import { TextEditorComponent } from '@ods/component';
 import { ButtonComponent, PlusIconComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
-import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
-import { singleColdCompleted } from '../../../../../tech-shared/test/marbles';
-import { createAggregationMappingResource } from '../../../../reporting-shared/test/aggregation-mapping';
-import { AdminCancelButtonComponent } from '../../../../shared/src/lib/admin-cancel-button/admin-cancel-button.component';
-import { AdminSaveButtonComponent } from '../../../../shared/src/lib/admin-save-button/admin-save-button.component';
-import { StatistikFieldsFormComponent } from './statistik-fields-form.component';
-import { StatistikFieldsMappingsFormComponent } from './statistik-fields-mappings-form/statistik-fields-mappings-form.component';
-import { StatistikFieldsFormService } from './statistik-fields.formservice';
-
-describe('AdminStatistikFieldsFormComponent', () => {
-  let component: StatistikFieldsFormComponent;
-  let fixture: ComponentFixture<StatistikFieldsFormComponent>;
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { createAggregationMappingResource } from '../../../../../reporting-shared/test/aggregation-mapping';
+import { AggregationMappingFieldListFormComponent } from './aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component';
+import { AggregationMappingFormComponent } from './aggregation-mapping-form.component';
+import { AggregationMappingFormService } from './aggregation-mapping-form.service';
+
+describe('AggregationMappingFormComponent', () => {
+  let component: AggregationMappingFormComponent;
+  let fixture: ComponentFixture<AggregationMappingFormComponent>;
 
   const formEngineNameInputTestId: string = getDataTestIdOf('form-engine-name');
   const formIdInputTestId: string = getDataTestIdOf('form-id');
@@ -39,37 +37,37 @@ describe('AdminStatistikFieldsFormComponent', () => {
 
   const formBuilder: FormBuilder = new FormBuilder();
 
-  let formService: Mock<StatistikFieldsFormService>;
+  let formService: Mock<AggregationMappingFormService>;
 
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
-      [StatistikFieldsFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
-      [StatistikFieldsFormService.FIELD_FORM_IDENTIFIER]: formBuilder.group({
-        [StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
-        [StatistikFieldsFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormService.FIELD_FORM_IDENTIFIER]: formBuilder.group({
+        [AggregationMappingFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
+        [AggregationMappingFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
       }),
     });
 
-    formService = <any>{ ...mock(StatistikFieldsFormService), form };
+    formService = <any>{ ...mock(AggregationMappingFormService), form };
     formService.get = jest.fn().mockReturnValue(of(aggregationMappingStateResource));
 
     await TestBed.configureTestingModule({
       imports: [
         ReactiveFormsModule,
-        StatistikFieldsFormComponent,
+        AggregationMappingFormComponent,
         MockComponent(TextEditorComponent),
         MockComponent(ButtonComponent),
         MockComponent(PlusIconComponent),
         MockComponent(AdminSaveButtonComponent),
         MockComponent(AdminCancelButtonComponent),
-        MockComponent(StatistikFieldsMappingsFormComponent),
+        MockComponent(AggregationMappingFieldListFormComponent),
       ],
     })
-      .overrideComponent(StatistikFieldsFormComponent, {
+      .overrideComponent(AggregationMappingFormComponent, {
         set: {
           providers: [
             {
-              provide: StatistikFieldsFormService,
+              provide: AggregationMappingFormService,
               useValue: formService,
             },
             {
@@ -81,7 +79,7 @@ describe('AdminStatistikFieldsFormComponent', () => {
       })
       .compileComponents();
 
-    fixture = TestBed.createComponent(StatistikFieldsFormComponent);
+    fixture = TestBed.createComponent(AggregationMappingFormComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts
similarity index 59%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts
index b5f78af0ec..d113a410a3 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts
@@ -7,12 +7,12 @@ import { ReactiveFormsModule } from '@angular/forms';
 import { SpinnerComponent, TextEditorComponent } from '@ods/component';
 import { ButtonComponent, PlusIconComponent } from '@ods/system';
 import { Observable } from 'rxjs';
-import { StatistikFieldsMappingsFormComponent } from './statistik-fields-mappings-form/statistik-fields-mappings-form.component';
-import { StatistikFieldsFormService } from './statistik-fields.formservice';
+import { AggregationMappingFieldListFormComponent } from './aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component';
+import { AggregationMappingFormService } from './aggregation-mapping-form.service';
 
 @Component({
-  selector: 'admin-statistik-fields-form',
-  templateUrl: './statistik-fields-form.component.html',
+  selector: 'admin-aggregation-mapping-form',
+  templateUrl: './aggregation-mapping-form.component.html',
   standalone: true,
   imports: [
     ButtonComponent,
@@ -20,19 +20,19 @@ import { StatistikFieldsFormService } from './statistik-fields.formservice';
     ReactiveFormsModule,
     AdminSaveButtonComponent,
     AdminCancelButtonComponent,
-    StatistikFieldsMappingsFormComponent,
+    AggregationMappingFieldListFormComponent,
     SpinnerComponent,
     AsyncPipe,
     TextEditorComponent,
   ],
-  providers: [{ provide: ADMIN_FORMSERVICE, useClass: StatistikFieldsFormService }],
+  providers: [{ provide: ADMIN_FORMSERVICE, useClass: AggregationMappingFormService }],
 })
-export class StatistikFieldsFormComponent {
-  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
+export class AggregationMappingFormComponent {
+  public readonly formService = <AggregationMappingFormService>inject(ADMIN_FORMSERVICE);
 
   public readonly aggregationMappingStateResource$: Observable<StateResource<AggregationMappingResource>> =
     this.formService.get();
 
-  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
+  public readonly AggregationMappingFormService = AggregationMappingFormService;
   public readonly Routes = ROUTES;
 }
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.service.ts
similarity index 71%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.service.ts
index 10ba7d8039..664ed43622 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.service.ts
@@ -5,7 +5,7 @@ import { FormArray, FormControl, FormGroup, UntypedFormGroup } from '@angular/fo
 import { filter, Observable, tap } from 'rxjs';
 
 @Injectable()
-export class StatistikFieldsFormService extends AbstractFormService<AggregationMappingResource> {
+export class AggregationMappingFormService extends AbstractFormService<AggregationMappingResource> {
   public static readonly FIELD_NAME: string = 'name';
   public static readonly FIELD_FORM_IDENTIFIER: string = 'formIdentifier';
   public static readonly FIELD_FORM_ENGINE_NAME: string = 'formEngineName';
@@ -18,12 +18,12 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
 
   protected initForm(): UntypedFormGroup {
     return this.formBuilder.group({
-      [StatistikFieldsFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
-      [StatistikFieldsFormService.FIELD_FORM_IDENTIFIER]: this.formBuilder.group({
-        [StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
-        [StatistikFieldsFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormService.FIELD_FORM_IDENTIFIER]: this.formBuilder.group({
+        [AggregationMappingFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
+        [AggregationMappingFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
       }),
-      [StatistikFieldsFormService.FIELD_MAPPINGS]: new FormArray([this.createArrayControl()]),
+      [AggregationMappingFormService.FIELD_MAPPINGS]: new FormArray([this.createArrayControl()]),
     });
   }
 
@@ -44,8 +44,8 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
 
   private createArrayControl(sourcePath: string = EMPTY_STRING, targetPath: string = EMPTY_STRING): FormGroup {
     return new FormGroup({
-      [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(sourcePath),
-      [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(targetPath),
+      [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(sourcePath),
+      [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(targetPath),
     });
   }
 
@@ -54,7 +54,7 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
   }
 
   public get mappings(): FormArray {
-    return this.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS] as FormArray;
+    return this.form.controls[AggregationMappingFormService.FIELD_MAPPINGS] as FormArray;
   }
 
   public get(): Observable<StateResource<AggregationMappingResource>> {
@@ -66,7 +66,7 @@ export class StatistikFieldsFormService extends AbstractFormService<AggregationM
 
   _patchForm(value: AggregationMappingResource): void {
     this.patch(value);
-    const mappingsFormArray: FormArray = this.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS] as FormArray;
+    const mappingsFormArray: FormArray = this.form.controls[AggregationMappingFormService.FIELD_MAPPINGS] as FormArray;
     mappingsFormArray.clear();
     value.mappings.forEach((mapping: FieldMapping) =>
       mappingsFormArray.push(this.createArrayControl(mapping.sourcePath, mapping.targetPath)),
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
similarity index 77%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
index 45f57f4bef..fab98f538a 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
@@ -30,11 +30,11 @@ import { expect } from '@jest/globals';
 import { createAggregationMapping, createAggregationMappingResource } from 'libs/admin/reporting-shared/test/aggregation-mapping';
 import { omit } from 'lodash-es';
 import { of } from 'rxjs';
-import { singleColdCompleted } from '../../../../../tech-shared/test/marbles';
-import { StatistikFieldsFormService } from './statistik-fields.formservice';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { AggregationMappingFormService } from './aggregation-mapping-form.service';
 
-describe('StatistikFieldsFormService', () => {
-  let formService: StatistikFieldsFormService;
+describe('AggregationMappingFormService', () => {
+  let formService: AggregationMappingFormService;
 
   let service: Mock<AggregationMappingService>;
 
@@ -42,10 +42,10 @@ describe('StatistikFieldsFormService', () => {
     service = mock(AggregationMappingService);
 
     TestBed.configureTestingModule({
-      providers: [StatistikFieldsFormService, { provide: AggregationMappingService, useValue: service }],
+      providers: [AggregationMappingFormService, { provide: AggregationMappingService, useValue: service }],
     });
 
-    formService = TestBed.inject(StatistikFieldsFormService);
+    formService = TestBed.inject(AggregationMappingFormService);
   });
 
   it('should create', () => {
@@ -83,31 +83,31 @@ describe('StatistikFieldsFormService', () => {
     it('should add mapping control', () => {
       formService.addMapping();
 
-      const mappingFormArray: FormArray = <FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS];
+      const mappingFormArray: FormArray = <FormArray>formService.form.controls[AggregationMappingFormService.FIELD_MAPPINGS];
       expect(mappingFormArray).toHaveLength(2);
       expect(mappingFormArray.controls[0].value).toEqual({
-        [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
-        [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+        [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
       });
     });
   });
 
   describe('remove mapping', () => {
     it('should remove mapping control', () => {
-      (<FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS]).push(
+      (<FormArray>formService.form.controls[AggregationMappingFormService.FIELD_MAPPINGS]).push(
         new FormGroup({
-          [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl('controlToRemove'),
-          [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl('controlToRemove'),
+          [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl('controlToRemove'),
+          [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl('controlToRemove'),
         }),
       );
 
       formService.removeMapping(1);
 
-      const mappingFormArray: FormArray = <FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS];
+      const mappingFormArray: FormArray = <FormArray>formService.form.controls[AggregationMappingFormService.FIELD_MAPPINGS];
       expect(mappingFormArray).toHaveLength(1);
       expect(mappingFormArray.controls[0].value).toEqual({
-        [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
-        [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+        [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
       });
     });
   });
@@ -118,8 +118,8 @@ describe('StatistikFieldsFormService', () => {
 
       expect(mappings).toHaveLength(1);
       expect(mappings.controls[0].value).toEqual({
-        [StatistikFieldsFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
-        [StatistikFieldsFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+        [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
       });
     });
   });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.html
similarity index 93%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.html
index 434802447a..a95bf3f3a4 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.html
@@ -23,7 +23,7 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<h1 class="heading-1" data-test-id="statistik-header-text">Statistik</h1>
+<h1 class="heading-1" data-test-id="aggregation-mapping-header-text">Statistik</h1>
 <ods-routing-button
   class="my-4 w-fit"
   [linkPath]="ROUTES.AGGREGATION_MAPPING_NEU"
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts
similarity index 87%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts
index 7407e0c895..f9fe5b7e4a 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts
@@ -31,12 +31,12 @@ import { singleCold } from 'libs/tech-shared/test/marbles';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
 import { createAggregationMappingListResource } from '../../../../reporting-shared/test/aggregation-mapping';
-import { AggregationMappingListComponent } from '../aggregation-mapping-list/aggregation-mapping-list.component';
-import { StatistikContainerComponent } from './statistik-container.component';
+import { AggregationMappingListContainerComponent } from './aggregation-mapping-list-container.component';
+import { AggregationMappingListComponent } from './aggregation-mapping-list/aggregation-mapping-list.component';
 
-describe('StatistikContainerComponent', () => {
-  let component: StatistikContainerComponent;
-  let fixture: ComponentFixture<StatistikContainerComponent>;
+describe('AggregationMappingListContainerComponent', () => {
+  let component: AggregationMappingListContainerComponent;
+  let fixture: ComponentFixture<AggregationMappingListContainerComponent>;
 
   let aggregationMappingService: Mock<AggregationMappingService>;
 
@@ -45,7 +45,7 @@ describe('StatistikContainerComponent', () => {
 
     await TestBed.configureTestingModule({
       imports: [
-        StatistikContainerComponent,
+        AggregationMappingListContainerComponent,
         MockComponent(RoutingButtonComponent),
         MockComponent(AggregationMappingListComponent),
       ],
@@ -57,7 +57,7 @@ describe('StatistikContainerComponent', () => {
       ],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(StatistikContainerComponent);
+    fixture = TestBed.createComponent(AggregationMappingListContainerComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.ts
similarity index 84%
rename from alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.ts
index 6465487752..622a61d5ef 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.ts
@@ -28,15 +28,15 @@ import { CommonModule } from '@angular/common';
 import { Component, inject, OnDestroy, OnInit } from '@angular/core';
 import { RoutingButtonComponent } from '@ods/component';
 import { Observable } from 'rxjs';
-import { AggregationMappingListComponent } from '../aggregation-mapping-list/aggregation-mapping-list.component';
+import { AggregationMappingListComponent } from './aggregation-mapping-list/aggregation-mapping-list.component';
 
 @Component({
-  selector: 'admin-statistik-container',
-  templateUrl: './statistik-container.component.html',
+  selector: 'admin-aggregation-mapping-list-container',
+  templateUrl: './aggregation-mapping-list-container.component.html',
   standalone: true,
   imports: [CommonModule, RoutingButtonComponent, AggregationMappingListComponent],
 })
-export class StatistikContainerComponent implements OnInit, OnDestroy {
+export class AggregationMappingListContainerComponent implements OnInit, OnDestroy {
   private service = inject(AggregationMappingService);
 
   public listStateResource$: Observable<StateResource<AggregationMappingListResource>>;
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
similarity index 100%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
similarity index 93%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
index 18d620f575..9a6061356d 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.spec.ts
@@ -4,8 +4,8 @@ import { getElementFromFixtureByType } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { expect } from '@jest/globals';
 import { ListItemComponent } from '@ods/system';
+import { createAggregationMappingResource } from 'libs/admin/reporting-shared/test/aggregation-mapping';
 import { MockComponent } from 'ng-mocks';
-import { createAggregationMappingResource } from '../../../../../reporting-shared/test/aggregation-mapping';
 import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item.component';
 
 describe('AggregationMappingListItemComponent', () => {
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
similarity index 100%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.ts
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.html
similarity index 100%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.html
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.html
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
similarity index 96%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
index dd1647f73a..c632c4a20b 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
@@ -12,8 +12,8 @@ import { expect } from '@jest/globals';
 import { SpinnerComponent } from '@ods/component';
 import { ListComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
-import { AggregationMappingListLinkRel } from '../../../../reporting-shared/src/lib/aggregation-mapping.linkrel';
-import { createAggregationMappingListResource } from '../../../../reporting-shared/test/aggregation-mapping';
+import { AggregationMappingListLinkRel } from '../../../../../reporting-shared/src/lib/aggregation-mapping.linkrel';
+import { createAggregationMappingListResource } from '../../../../../reporting-shared/test/aggregation-mapping';
 import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item/aggregation-mapping-list-item.component';
 import { AggregationMappingListComponent } from './aggregation-mapping-list.component';
 
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.ts
similarity index 92%
rename from alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.ts
index c427bc7903..4adecffe51 100644
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-list/aggregation-mapping-list.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.ts
@@ -3,7 +3,7 @@ import { createEmptyStateResource, getEmbeddedResources, isLoaded, isNotNil, Sta
 import { Component, Input } from '@angular/core';
 import { SpinnerComponent } from '@ods/component';
 import { ListComponent } from '@ods/system';
-import { AggregationMappingListLinkRel } from '../../../../reporting-shared/src/lib/aggregation-mapping.linkrel';
+import { AggregationMappingListLinkRel } from 'libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel';
 import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item/aggregation-mapping-list-item.component';
 
 @Component({
diff --git a/alfa-client/libs/admin/statistik/src/test-setup.ts b/alfa-client/libs/admin/aggregation-mapping/src/test-setup.ts
similarity index 100%
rename from alfa-client/libs/admin/statistik/src/test-setup.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/test-setup.ts
diff --git a/alfa-client/libs/admin/statistik/tsconfig.json b/alfa-client/libs/admin/aggregation-mapping/tsconfig.json
similarity index 100%
rename from alfa-client/libs/admin/statistik/tsconfig.json
rename to alfa-client/libs/admin/aggregation-mapping/tsconfig.json
diff --git a/alfa-client/libs/admin/statistik/tsconfig.lib.json b/alfa-client/libs/admin/aggregation-mapping/tsconfig.lib.json
similarity index 100%
rename from alfa-client/libs/admin/statistik/tsconfig.lib.json
rename to alfa-client/libs/admin/aggregation-mapping/tsconfig.lib.json
diff --git a/alfa-client/libs/admin/statistik/tsconfig.spec.json b/alfa-client/libs/admin/aggregation-mapping/tsconfig.spec.json
similarity index 100%
rename from alfa-client/libs/admin/statistik/tsconfig.spec.json
rename to alfa-client/libs/admin/aggregation-mapping/tsconfig.spec.json
diff --git a/alfa-client/libs/admin/statistik/README.md b/alfa-client/libs/admin/statistik/README.md
deleted file mode 100644
index ad651ba5c6..0000000000
--- a/alfa-client/libs/admin/statistik/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# statistik
-
-This library was generated with [Nx](https://nx.dev).
-
-## Running unit tests
-
-Run `nx test statistik` to execute the unit tests.
diff --git a/alfa-client/libs/admin/statistik/src/index.ts b/alfa-client/libs/admin/statistik/src/index.ts
deleted file mode 100644
index c2e36a7669..0000000000
--- a/alfa-client/libs/admin/statistik/src/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component';
-export * from './lib/statistik-container/statistik-container.component';
-export * from './lib/statistik-fields-form/statistik-fields-form.component';
diff --git a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html b/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
deleted file mode 100644
index e6db36aca8..0000000000
--- a/alfa-client/libs/admin/statistik/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<ods-spinner [stateResource]="listStateResource$ | async">
-  <admin-statistik-fields-form data-test-id="evaluate-fields-form"></admin-statistik-fields-form>
-</ods-spinner>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html
deleted file mode 100644
index 7e2804257f..0000000000
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<form [formGroup]="formService.form">
-  <div class="flex flex-col" [formArrayName]="StatistikFieldsFormService.FIELD_MAPPINGS">
-    <div *ngFor="let ignore of mappingsFormArray; let i = index">
-      <admin-statistik-field-mapping-form
-        [index]="i"
-        [attr.data-test-id]="'statistik-field-mapping-form-' + i"
-      ></admin-statistik-field-mapping-form>
-    </div>
-  </div>
-</form>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts
deleted file mode 100644
index ff8b9135d1..0000000000
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-mappings-form/statistik-fields-mappings-form.component.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { ADMIN_FORMSERVICE } from '@admin-client/shared';
-import { CommonModule } from '@angular/common';
-import { Component, inject } from '@angular/core';
-import { AbstractControl, ReactiveFormsModule } from '@angular/forms';
-import { StatistikFieldsFormService } from '../statistik-fields.formservice';
-import { StatistikFieldMappingFormComponent } from './statistik-field-mapping-form/statistik-field-mapping-form.component';
-
-@Component({
-  selector: 'admin-statistik-fields-form-mapping',
-  templateUrl: './statistik-fields-mappings-form.component.html',
-  standalone: true,
-  imports: [CommonModule, ReactiveFormsModule, StatistikFieldMappingFormComponent],
-})
-export class StatistikFieldsMappingsFormComponent {
-  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
-
-  public readonly mappingsFormArray: AbstractControl[] = this.formService.mappings.controls;
-
-  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
-}
diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json
index 615131502b..210fd016c7 100644
--- a/alfa-client/tsconfig.base.json
+++ b/alfa-client/tsconfig.base.json
@@ -25,7 +25,7 @@
       "@admin-client/reporting-shared": ["libs/admin/reporting-shared/src/index.ts"],
       "@admin-client/settings-shared": ["libs/admin/settings-shared/src/index.ts"],
       "@admin-client/shared": ["libs/admin/shared/src/index.ts"],
-      "@admin-client/statistik": ["libs/admin/statistik/src/index.ts"],
+      "@admin-client/aggregation-mapping": ["libs/admin/aggregation-mapping/src/index.ts"],
       "@admin-client/user": ["libs/admin/user/src/index.ts"],
       "@admin-client/user-shared": ["libs/admin/user-shared/src/index.ts"],
       "@admin/keycloak-shared": ["libs/admin/keycloak-shared/src/index.ts"],
-- 
GitLab


From 977be8435064a16ade8a4f5a8e9ee16f00d6c770 Mon Sep 17 00:00:00 2001
From: Albert <Albert.Bruns@mgm-tp.com>
Date: Thu, 20 Mar 2025 09:46:55 +0100
Subject: [PATCH 16/47] OZG-7473-7885 ui ux

---
 ...regation-mapping-field-form.component.html |  2 +-
 ...gregation-mapping-list-item.component.html | 21 +++++++++----------
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
index c5f184738c..0a030c5f7d 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
@@ -1,7 +1,7 @@
 <form [formGroup]="formService.form">
   <ng-container [formArrayName]="AggregationMappingFormService.FIELD_MAPPINGS">
     <ng-container [formGroupName]="index">
-      <div class="flex w-full flex-col gap-2 mt-4 bg-gray-100 p-4 rounded-md">
+      <div class="flex w-full flex-col gap-2 mt-4 bg-background-100 p-4 rounded-md">
         <div class="flex flex-row items-center justify-between">
           <p class="text-md mb-2 block font-medium text-text">Datenfeld</p>
           <ods-button
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
index 777c081ff0..6a04409309 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -1,17 +1,16 @@
 <ods-list-item [path]="aggregationMapping | toResourceUri" [attr.data-test-id]="aggregationMapping.name | convertForDataTest">
-  <dl class="flex-1 font-semibold">
-    <dt class="sr-only">Name</dt>
-    <dd data-test-class="fullname">{{ aggregationMapping.name }}</dd>
-  </dl>
-  <!-- Remove null safe check operator after backend provides correct data. -->
-  <div class="flex-1 flex-wrap">
-    <dl>
+  <dl class="flex w-full">
+    <div class="w-1/2">
+      <dt class="sr-only">Name</dt>
+      <dd class="font-semibold" data-test-class="fullname">{{ aggregationMapping.name }}</dd>
+    </div>
+    <!-- Remove null safe check operator after backend provides correct data. -->
+    <div class="flex-wrap w-1/2">
       <dt class="sr-only">Formengine</dt>
       <dd>{{ aggregationMapping.formIdentifier?.formEngineName }}</dd>
-    </dl>
-    <dl>
+
       <dt class="sr-only">Form ID</dt>
       <dd>{{ aggregationMapping.formIdentifier?.formId }}</dd>
-    </dl>
-  </div>
+    </div>
+  </dl>
 </ods-list-item>
-- 
GitLab


From 9f1798ca1838c8da6c06b24fdb1e16624eaf08d0 Mon Sep 17 00:00:00 2001
From: Albert <Albert.Bruns@mgm-tp.com>
Date: Fri, 21 Mar 2025 09:51:47 +0100
Subject: [PATCH 17/47] OZG-7473 e2e

---
 .../aggregation-mapping-form.e2e.component.ts | 48 +++++-------
 .../aggregation-mapping.e2e.component.ts      | 23 +++++-
 .../aggregation-mapping.cy.ts                 | 75 ++++++++++++-------
 .../aggregation-mapping.helper.ts             | 65 ++++++++++++++++
 .../admin-e2e/src/support/cypress-helper.ts   |  2 +
 ...ggregation-mapping-field-form.component.ts |  2 +-
 ...ion-mapping-field-list-form.component.html |  4 +-
 ...gregation-mapping-list-item.component.html |  4 +-
 8 files changed, 160 insertions(+), 63 deletions(-)
 create mode 100644 alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts

diff --git a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
index 112cc9e0aa..2545b8b6b6 100644
--- a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
@@ -1,67 +1,57 @@
-import { enterWith } from '../../support/cypress.util';
-
 export class AggregationMappingFormE2EComponent {
+  private readonly rootElement: string = 'aggregation-mapping-form';
+  private readonly nameInput: string = 'aggregation-mapping-name-text-input';
   private readonly formEngineInput: string = 'form-engine-name-text-input';
   private readonly formIdInput: string = 'form-id-text-input';
-  private readonly formDataFieldInput: string = 'mapping-field-';
+  private readonly dataFieldInputPrefix: string = 'aggregation-mapping-field-mapping-form-';
+  private readonly sourceMappingFieldInputPrefix: string = 'source-mapping-field-';
+  private readonly targetMappingFieldInputPrefix: string = 'target-mapping-field-';
   private readonly addDataFieldButton: string = 'add-mapping-button';
   private readonly deleteDataFieldButtonPrefix: string = 'remove-mapping-button-';
   private readonly saveButton: string = 'save-button';
   private readonly cancelButton: string = 'cancel-button';
 
-  public getFormEngineInput(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.formEngineInput);
+  public getRootElement(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.rootElement);
   }
 
-  public enterFormEngine(text: string): void {
-    enterWith(this.getFormEngineInput(), text);
+  public getNameInput(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.nameInput);
+  }
+
+  public getFormEngineInput(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.formEngineInput);
   }
 
   public getFormIdInput(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.formIdInput);
   }
 
-  public enterFormId(text: string): void {
-    enterWith(this.getFormIdInput(), text);
+  public getDataFieldInput(index: number): Cypress.Chainable<Element> {
+    return cy.getTestElement(`${this.dataFieldInputPrefix}${index}`);
   }
 
   public getAddFieldButton(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.addDataFieldButton);
   }
 
-  public addField(): void {
-    this.getAddFieldButton().click();
+  public getSourceMappingFieldInput(index: number): Cypress.Chainable<Element> {
+    return cy.getTestElement(`${this.sourceMappingFieldInputPrefix}${index}-text-input`);
   }
 
-  public getDataFieldInput(index: number): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.formDataFieldInput + index + '-text-input');
-  }
-
-  public enterDataFieldPath(text: string, index: number): void {
-    enterWith(this.getDataFieldInput(index), text);
+  public getTargetMappingFieldInput(index: number): Cypress.Chainable<Element> {
+    return cy.getTestElement(`${this.targetMappingFieldInputPrefix}${index}-text-input`);
   }
 
   public getDataFieldDeleteButton(index: number): Cypress.Chainable<Element> {
     return cy.getTestElement(this.deleteDataFieldButtonPrefix + index);
   }
 
-  public deleteDataField(index: number): void {
-    this.getDataFieldDeleteButton(index).click();
-  }
-
   public getSaveButton(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.saveButton);
   }
 
-  public save(): void {
-    this.getSaveButton().click();
-  }
-
   public getCancelButton(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.cancelButton);
   }
-
-  public cancel(): void {
-    this.getCancelButton().click();
-  }
 }
diff --git a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
index 8e9ad4a76d..10e67b06e5 100644
--- a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
@@ -1,12 +1,27 @@
 export class AggregationMappingE2EComponent {
-  private readonly locatorHeaderText: string = 'aggregation-mapping-header-text';
-  private readonly locatorWeitereFelderAuswertenButton = 'weitere-felder-auswerten-button';
+  private readonly headerText: string = 'aggregation-mapping-header-text';
+  private readonly listItemName: string = 'list-item-name';
+  private readonly listItemFormEngineName: string = 'list-item-form-engine-name';
+  private readonly listItemFormId: string = 'list-item-form-id';
+  private readonly weitereFelderAuswertenButton = 'weitere-felder-auswerten-button';
 
   public getHeaderText(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.locatorHeaderText);
+    return cy.getTestElement(this.headerText);
+  }
+
+  public getListItemName(): Cypress.Chainable<Element> {
+    return cy.getTestElementWithClass(this.listItemName);
+  }
+
+  public getListItemFormEngineName(): Cypress.Chainable<Element> {
+    return cy.getTestElementWithClass(this.listItemFormEngineName);
+  }
+
+  public getListItemFormId(): Cypress.Chainable<Element> {
+    return cy.getTestElementWithClass(this.listItemFormId);
   }
 
   public getWeitereFelderAuswertenButton(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.locatorWeitereFelderAuswertenButton);
+    return cy.getTestElement(this.weitereFelderAuswertenButton);
   }
 }
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
index 91ed35a2dd..e1a594ff31 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
@@ -1,57 +1,82 @@
+import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared';
 import { AggregationMappingFormE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping-form.e2e.component';
 import { AggregationMappingE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping.e2e.component';
-import { exist, haveValue } from '../../../support/cypress.util';
+import { E2EAggregationMappingHelper } from '../../../helper/aggregation-mapping/aggregation-mapping.helper';
+import { dropCollections } from '../../../support/cypress-helper';
+import { exist, notExist } from '../../../support/cypress.util';
 import { loginAsDaria } from '../../../support/user-util';
 
 describe('Aggregation Mapping hinzufügen', () => {
   const component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
-  const fieldsFormComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
+  const formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
 
-  const dataText1: string = 'Eingabe A';
-  const dataText2: string = 'Eingabe B';
+  const helper: E2EAggregationMappingHelper = new E2EAggregationMappingHelper();
+
+  const fieldMapping0: FieldMapping = {
+    sourcePath: '/path/to/source/a',
+    targetPath: '/path/to/target/a',
+  };
+
+  const fieldMapping1: FieldMapping = {
+    sourcePath: '/path/to/source/b',
+    targetPath: '/path/to/target/b',
+  };
+
+  const aggregationMapping: AggregationMapping = {
+    name: 'Aggregation Mapping',
+    formIdentifier: {
+      formEngineName: 'formEngineName',
+      formId: 'formId',
+    },
+    mappings: [fieldMapping0, fieldMapping1],
+  };
 
   before(() => {
     loginAsDaria();
   });
 
+  after(() => {
+    dropCollections();
+  });
+
   it('should show "Weitere Felder auswerten" button', () => {
     exist(component.getWeitereFelderAuswertenButton());
   });
 
-  it('should have all form elements after button click', () => {
+  it('should show form after button click', () => {
     component.getWeitereFelderAuswertenButton().click();
 
-    exist(fieldsFormComponent.getFormEngineInput());
-    exist(fieldsFormComponent.getFormIdInput());
-    exist(fieldsFormComponent.getDataFieldInput(0));
-    exist(fieldsFormComponent.getDataFieldDeleteButton(0));
-    exist(fieldsFormComponent.getAddFieldButton());
-    exist(fieldsFormComponent.getSaveButton());
-    exist(fieldsFormComponent.getCancelButton());
+    exist(formComponent.getRootElement());
+  });
+
+  it('should navigate to aggregation mapping on cancel', () => {
+    formComponent.getCancelButton().click();
+
+    exist(component.getWeitereFelderAuswertenButton());
   });
 
-  it('should add data field', () => {
-    fieldsFormComponent.addField();
+  it('should add data field in form', () => {
+    component.getWeitereFelderAuswertenButton().click();
+    formComponent.getAddFieldButton().click();
 
-    exist(fieldsFormComponent.getDataFieldInput(1));
+    exist(formComponent.getDataFieldInput(1));
   });
 
-  it('should enter text in both data fields', () => {
-    fieldsFormComponent.enterDataFieldPath(dataText1, 0);
-    fieldsFormComponent.enterDataFieldPath(dataText2, 1);
+  it('should fill out form with two data fields', () => {
+    helper.enterForm(aggregationMapping);
 
-    haveValue(fieldsFormComponent.getDataFieldInput(0), dataText1);
-    haveValue(fieldsFormComponent.getDataFieldInput(1), dataText2);
+    helper.verifyForm(aggregationMapping);
   });
 
   it('should delete data fields', () => {
-    fieldsFormComponent.deleteDataField(0);
-    haveValue(fieldsFormComponent.getDataFieldInput(0), dataText2);
+    formComponent.getDataFieldDeleteButton(0).click();
+
+    notExist(formComponent.getDataFieldInput(1));
   });
 
-  it('should navigate to aggregation mapping on cancel', () => {
-    fieldsFormComponent.cancel();
+  it('should show aggregation mapping in list after save', () => {
+    formComponent.getSaveButton().click();
 
-    exist(component.getWeitereFelderAuswertenButton());
+    helper.verifyAggregationMappingInList(aggregationMapping);
   });
 });
diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts
new file mode 100644
index 0000000000..b36249dc2f
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts
@@ -0,0 +1,65 @@
+import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared';
+import { AggregationMappingFormE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping-form.e2e.component';
+import { AggregationMappingE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping.e2e.component';
+import { enterWith, haveText, haveValue } from '../../support/cypress.util';
+
+export class E2EAggregationMappingHelper {
+  private component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
+  private formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
+
+  public enterName(text: string): void {
+    enterWith(this.formComponent.getNameInput(), text);
+  }
+
+  public enterFormEngine(text: string): void {
+    enterWith(this.formComponent.getFormEngineInput(), text);
+  }
+
+  public enterFormId(text: string): void {
+    enterWith(this.formComponent.getFormIdInput(), text);
+  }
+
+  public enterSourcePath(text: string, index: number): void {
+    enterWith(this.formComponent.getSourceMappingFieldInput(index), text);
+  }
+
+  public enterTargetPath(text: string, index: number): void {
+    enterWith(this.formComponent.getTargetMappingFieldInput(index), text);
+  }
+
+  public enterFieldMapping(fieldMapping: FieldMapping, index: number): void {
+    this.enterSourcePath(fieldMapping.sourcePath, index);
+    this.enterTargetPath(fieldMapping.targetPath, index);
+  }
+
+  public enterForm(aggregationMapping: AggregationMapping): void {
+    this.enterName(aggregationMapping.name);
+    this.enterFormEngine(aggregationMapping.formIdentifier.formEngineName);
+    this.enterFormId(aggregationMapping.formIdentifier.formId);
+
+    aggregationMapping.mappings.forEach((fieldMapping, index) => {
+      this.enterFieldMapping(fieldMapping, index);
+    });
+  }
+
+  public verifyFieldMapping(fieldMapping: FieldMapping, index: number): void {
+    haveValue(this.formComponent.getSourceMappingFieldInput(index), fieldMapping.sourcePath);
+    haveValue(this.formComponent.getTargetMappingFieldInput(index), fieldMapping.targetPath);
+  }
+
+  public verifyForm(aggregationMapping: AggregationMapping): void {
+    haveValue(this.formComponent.getNameInput(), aggregationMapping.name);
+    haveValue(this.formComponent.getFormEngineInput(), aggregationMapping.formIdentifier.formEngineName);
+    haveValue(this.formComponent.getFormIdInput(), aggregationMapping.formIdentifier.formId);
+
+    aggregationMapping.mappings.forEach((fieldMapping, index) => {
+      this.verifyFieldMapping(fieldMapping, index);
+    });
+  }
+
+  public verifyAggregationMappingInList(aggregationMapping: AggregationMapping): void {
+    haveText(this.component.getListItemName(), aggregationMapping.name);
+    haveText(this.component.getListItemFormEngineName(), aggregationMapping.formIdentifier.formEngineName);
+    haveText(this.component.getListItemFormId(), aggregationMapping.formIdentifier.formId);
+  }
+}
diff --git a/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts b/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts
index a48d664eb7..83e7bb11f0 100644
--- a/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts
+++ b/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts
@@ -31,6 +31,7 @@ enum CypressTasks {
 
 enum MongoCollections {
   ORGANISATIONS_EINHEIT = 'organisationsEinheit',
+  SETTINGS = 'settings',
 }
 
 const DOWNLOAD_FOLDER: string = 'cypress/downloads';
@@ -110,4 +111,5 @@ export function initOrganisationsEinheitenData(data: OrganisationsEinheitE2E[]):
 
 export function dropCollections() {
   cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.ORGANISATIONS_EINHEIT]);
+  cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.SETTINGS]);
 }
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
index e80a74f035..d7e2e1f162 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
@@ -6,7 +6,7 @@ import { ButtonComponent, DeleteIconComponent } from '@ods/system';
 import { AggregationMappingFormService } from '../../aggregation-mapping-form.service';
 
 @Component({
-  selector: 'admin-aggregatin-mapping-field-form',
+  selector: 'admin-aggregation-mapping-field-form',
   standalone: true,
   templateUrl: './aggregation-mapping-field-form.component.html',
   imports: [ButtonComponent, DeleteIconComponent, ReactiveFormsModule, TextEditorComponent],
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
index ee829b2a70..958c7f9d5f 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
@@ -1,10 +1,10 @@
 <form [formGroup]="formService.form">
   <div class="flex flex-col" [formArrayName]="AggregationMappingFormService.FIELD_MAPPINGS">
     <div *ngFor="let ignore of mappingsFormArray; let i = index">
-      <admin-aggregatin-mapping-field-form
+      <admin-aggregation-mapping-field-form
         [index]="i"
         [attr.data-test-id]="'aggregation-mapping-field-mapping-form-' + i"
-      ></admin-aggregatin-mapping-field-form>
+      ></admin-aggregation-mapping-field-form>
     </div>
   </div>
 </form>
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
index 6a04409309..d7d2401653 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -1,11 +1,11 @@
 <ods-list-item [path]="aggregationMapping | toResourceUri" [attr.data-test-id]="aggregationMapping.name | convertForDataTest">
   <dl class="flex w-full">
-    <div class="w-1/2">
+    <div class="flex-1">
       <dt class="sr-only">Name</dt>
       <dd class="font-semibold" data-test-class="fullname">{{ aggregationMapping.name }}</dd>
     </div>
     <!-- Remove null safe check operator after backend provides correct data. -->
-    <div class="flex-wrap w-1/2">
+    <div class="flex-wrap flex-1">
       <dt class="sr-only">Formengine</dt>
       <dd>{{ aggregationMapping.formIdentifier?.formEngineName }}</dd>
 
-- 
GitLab


From 6b71b9cf8cc99015dd1535b4ee78100d9c8acd4f Mon Sep 17 00:00:00 2001
From: Albert <Albert.Bruns@mgm-tp.com>
Date: Fri, 21 Mar 2025 09:52:58 +0100
Subject: [PATCH 18/47] OZG-7473 e2e

---
 .../aggregation-mapping-form-container.component.html       | 2 +-
 .../aggregation-mapping-list-item.component.html            | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
index ac4fc2d0cc..4cccfbe689 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form-container.component.html
@@ -1,3 +1,3 @@
 <ods-spinner [stateResource]="listStateResource$ | async">
-  <admin-aggregation-mapping-form data-test-id="evaluate-fields-form"></admin-aggregation-mapping-form>
+  <admin-aggregation-mapping-form data-test-id="aggregation-mapping-form" />
 </ods-spinner>
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
index d7d2401653..6b1643e863 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -2,15 +2,15 @@
   <dl class="flex w-full">
     <div class="flex-1">
       <dt class="sr-only">Name</dt>
-      <dd class="font-semibold" data-test-class="fullname">{{ aggregationMapping.name }}</dd>
+      <dd class="font-semibold" data-test-class="list-item-name">{{ aggregationMapping.name }}</dd>
     </div>
     <!-- Remove null safe check operator after backend provides correct data. -->
     <div class="flex-wrap flex-1">
       <dt class="sr-only">Formengine</dt>
-      <dd>{{ aggregationMapping.formIdentifier?.formEngineName }}</dd>
+      <dd data-test-class="list-item-form-engine-name">{{ aggregationMapping.formIdentifier?.formEngineName }}</dd>
 
       <dt class="sr-only">Form ID</dt>
-      <dd>{{ aggregationMapping.formIdentifier?.formId }}</dd>
+      <dd data-test-class="list-item-form-id">{{ aggregationMapping.formIdentifier?.formId }}</dd>
     </div>
   </dl>
 </ods-list-item>
-- 
GitLab


From 4b8654b7482199718686bf1d599b9a5b7b91f123 Mon Sep 17 00:00:00 2001
From: Martin <git@mail.de>
Date: Fri, 21 Mar 2025 13:28:05 +0100
Subject: [PATCH 19/47] OZG-7473 rename getRootElement -> getRoot

---
 .../aggregation-mapping-form.e2e.component.ts              | 7 ++++---
 .../aggregation-mapping/aggregation-mapping.cy.ts          | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
index 2545b8b6b6..e140ef0486 100644
--- a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts
@@ -1,5 +1,6 @@
 export class AggregationMappingFormE2EComponent {
-  private readonly rootElement: string = 'aggregation-mapping-form';
+  private readonly root: string = 'aggregation-mapping-form';
+
   private readonly nameInput: string = 'aggregation-mapping-name-text-input';
   private readonly formEngineInput: string = 'form-engine-name-text-input';
   private readonly formIdInput: string = 'form-id-text-input';
@@ -11,8 +12,8 @@ export class AggregationMappingFormE2EComponent {
   private readonly saveButton: string = 'save-button';
   private readonly cancelButton: string = 'cancel-button';
 
-  public getRootElement(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.rootElement);
+  public getRoot(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.root);
   }
 
   public getNameInput(): Cypress.Chainable<Element> {
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
index e1a594ff31..48a51be178 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
@@ -46,7 +46,7 @@ describe('Aggregation Mapping hinzufügen', () => {
   it('should show form after button click', () => {
     component.getWeitereFelderAuswertenButton().click();
 
-    exist(formComponent.getRootElement());
+    exist(formComponent.getRoot());
   });
 
   it('should navigate to aggregation mapping on cancel', () => {
-- 
GitLab


From 8335b8f92dca68d469e8b4a6ab8d652542b04457 Mon Sep 17 00:00:00 2001
From: Oliver Schmidt <kontakt@webkreation.de>
Date: Fri, 21 Mar 2025 14:52:36 +0100
Subject: [PATCH 20/47] OZG-7473-7959 ui layout

---
 ...regation-mapping-field-form.component.html | 40 +++++++++----------
 .../aggregation-mapping-form.component.html   | 25 +++++++-----
 2 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
index 0a030c5f7d..8469852f2b 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
@@ -1,9 +1,9 @@
 <form [formGroup]="formService.form">
   <ng-container [formArrayName]="AggregationMappingFormService.FIELD_MAPPINGS">
     <ng-container [formGroupName]="index">
-      <div class="flex w-full flex-col gap-2 mt-4 bg-background-100 p-4 rounded-md">
+      <div class="mt-4 flex w-full flex-col rounded-md bg-background-150 p-4">
         <div class="flex flex-row items-center justify-between">
-          <p class="text-md mb-2 block font-medium text-text">Datenfeld</p>
+          <p class="mb-2 block text-lg font-medium text-text">Datenfeld</p>
           <ods-button
             class="self-end"
             variant="ghost"
@@ -16,24 +16,24 @@
             <ods-delete-icon icon />
           </ods-button>
         </div>
-        <ods-text-editor
-          class="flex-1"
-          formControlName="sourcePath"
-          label="Pfad"
-          placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
-          isRequired="true"
-          [dataTestId]="'source-mapping-field-' + index"
-          [attr.data-test-id]="'source-mapping-field-' + index"
-        ></ods-text-editor>
-        <ods-text-editor
-          class="flex-1"
-          formControlName="targetPath"
-          label="Zielfeld"
-          isRequired="true"
-          placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
-          [dataTestId]="'target-mapping-field-' + index"
-          [attr.data-test-id]="'target-mapping-field-' + index"
-        ></ods-text-editor>
+        <div class="flex flex-col gap-4">
+          <ods-text-editor
+            formControlName="sourcePath"
+            label="Pfad"
+            placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
+            isRequired="true"
+            [dataTestId]="'source-mapping-field-' + index"
+            [attr.data-test-id]="'source-mapping-field-' + index"
+          ></ods-text-editor>
+          <ods-text-editor
+            formControlName="targetPath"
+            label="Zielfeld"
+            isRequired="true"
+            placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
+            [dataTestId]="'target-mapping-field-' + index"
+            [attr.data-test-id]="'target-mapping-field-' + index"
+          ></ods-text-editor>
+        </div>
       </div>
     </ng-container>
   </ng-container>
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
index abcbef7402..b69813d98a 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
@@ -2,17 +2,21 @@
 
 <ods-spinner [stateResource]="aggregationMappingStateResource$ | async">
   <div class="flex max-w-4xl flex-col gap-4">
-    <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-2">
-      <ods-text-editor
-        [formControlName]="AggregationMappingFormService.FIELD_NAME"
-        label="Name"
-        placeholder=""
-        isRequired="true"
-        data-test-id="aggregation-mapping-name-text-editor"
-        dataTestId="aggregation-mapping-name"
-      ></ods-text-editor>
-      <div [formGroupName]="AggregationMappingFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
+    <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-4">
+      <div class="flex flex-col gap-4 lg:flex-row">
         <ods-text-editor
+          class="basis-1/2 lg:pr-2"
+          [formControlName]="AggregationMappingFormService.FIELD_NAME"
+          label="Name"
+          placeholder=""
+          isRequired="true"
+          data-test-id="aggregation-mapping-name-text-editor"
+          dataTestId="aggregation-mapping-name"
+        ></ods-text-editor>
+      </div>
+      <div [formGroupName]="AggregationMappingFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4 lg:flex-row">
+        <ods-text-editor
+          class="flex-1"
           [formControlName]="AggregationMappingFormService.FIELD_FORM_ENGINE_NAME"
           label="Formengine"
           placeholder="Tragen Sie hier die Formengine des Formulars ein."
@@ -21,6 +25,7 @@
           dataTestId="form-engine-name"
         ></ods-text-editor>
         <ods-text-editor
+          class="flex-1"
           [formControlName]="AggregationMappingFormService.FIELD_FORM_ID"
           label="FormID"
           placeholder="Tragen Sie hier die FormID des Formulars ein."
-- 
GitLab


From 60246384d7c7525b7e7144413aee084ec1b42047 Mon Sep 17 00:00:00 2001
From: Martin <git@mail.de>
Date: Fri, 21 Mar 2025 15:22:34 +0100
Subject: [PATCH 21/47] OZG-7473 adjust component/structure; rename db settings
 -> aggregationMapping

---
 .../aggregation-mapping.e2e.component.ts      | 42 +++++++++---
 .../aggregation-mapping.cy.ts                 | 36 +++++-----
 .../aggregation-mapping.executor.ts           | 22 ++++++
 .../aggregation-mapping.helper.ts             | 67 +++----------------
 .../aggregation-mapping.navigator.ts          | 18 +++++
 .../aggregation-mapping.verifier.ts           | 34 ++++++++++
 .../apps/admin-e2e/src/helper/app.helper.ts   |  9 +++
 .../admin-e2e/src/page-objects/main.po.ts     |  2 +-
 .../admin-e2e/src/support/cypress-helper.ts   |  8 +--
 9 files changed, 148 insertions(+), 90 deletions(-)
 create mode 100644 alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.executor.ts
 create mode 100644 alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.navigator.ts
 create mode 100644 alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier.ts
 create mode 100644 alfa-client/apps/admin-e2e/src/helper/app.helper.ts

diff --git a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
index 10e67b06e5..69df7bcede 100644
--- a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts
@@ -1,27 +1,47 @@
+import { getTestElement } from '../../support/cypress-helper';
+import { convertToDataTestId } from '../../support/tech-util';
+
 export class AggregationMappingE2EComponent {
   private readonly headerText: string = 'aggregation-mapping-header-text';
-  private readonly listItemName: string = 'list-item-name';
-  private readonly listItemFormEngineName: string = 'list-item-form-engine-name';
-  private readonly listItemFormId: string = 'list-item-form-id';
   private readonly weitereFelderAuswertenButton = 'weitere-felder-auswerten-button';
 
   public getHeaderText(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.headerText);
   }
 
-  public getListItemName(): Cypress.Chainable<Element> {
-    return cy.getTestElementWithClass(this.listItemName);
+  public getWeitereFelderAuswertenButton(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.weitereFelderAuswertenButton);
+  }
+
+  public getListItem(name: string): AggregationMappingListItemE2EComponent {
+    return new AggregationMappingListItemE2EComponent(name);
+  }
+}
+
+export class AggregationMappingListItemE2EComponent {
+  private root: string;
+
+  private readonly listItemName: string = 'list-item-name';
+  private readonly listItemFormEngineName: string = 'list-item-form-engine-name';
+  private readonly listItemFormId: string = 'list-item-form-id';
+
+  constructor(root: string) {
+    this.root = convertToDataTestId(root);
   }
 
-  public getListItemFormEngineName(): Cypress.Chainable<Element> {
-    return cy.getTestElementWithClass(this.listItemFormEngineName);
+  public getRoot(): Cypress.Chainable<Element> {
+    return getTestElement(this.root);
   }
 
-  public getListItemFormId(): Cypress.Chainable<Element> {
-    return cy.getTestElementWithClass(this.listItemFormId);
+  public getName(): Cypress.Chainable<Element> {
+    return this.getRoot().findTestElementWithClass(this.listItemName);
   }
 
-  public getWeitereFelderAuswertenButton(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.weitereFelderAuswertenButton);
+  public getFormEngineName(): Cypress.Chainable<Element> {
+    return this.getRoot().findTestElementWithClass(this.listItemFormEngineName);
+  }
+
+  public getFormId(): Cypress.Chainable<Element> {
+    return this.getRoot().findTestElementWithClass(this.listItemFormId);
   }
 }
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
index 48a51be178..ffabc87021 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts
@@ -1,4 +1,5 @@
 import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared';
+import { E2EAggregationMappingVerifier } from 'apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier';
 import { AggregationMappingFormE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping-form.e2e.component';
 import { AggregationMappingE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping.e2e.component';
 import { E2EAggregationMappingHelper } from '../../../helper/aggregation-mapping/aggregation-mapping.helper';
@@ -7,10 +8,11 @@ import { exist, notExist } from '../../../support/cypress.util';
 import { loginAsDaria } from '../../../support/user-util';
 
 describe('Aggregation Mapping hinzufügen', () => {
-  const component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
-  const formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
+  const page: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
+  const form: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
 
   const helper: E2EAggregationMappingHelper = new E2EAggregationMappingHelper();
+  const verifier: E2EAggregationMappingVerifier = new E2EAggregationMappingVerifier();
 
   const fieldMapping0: FieldMapping = {
     sourcePath: '/path/to/source/a',
@@ -40,43 +42,45 @@ describe('Aggregation Mapping hinzufügen', () => {
   });
 
   it('should show "Weitere Felder auswerten" button', () => {
-    exist(component.getWeitereFelderAuswertenButton());
+    helper.openStatistik();
+
+    exist(page.getWeitereFelderAuswertenButton());
   });
 
   it('should show form after button click', () => {
-    component.getWeitereFelderAuswertenButton().click();
+    page.getWeitereFelderAuswertenButton().click();
 
-    exist(formComponent.getRoot());
+    exist(form.getRoot());
   });
 
   it('should navigate to aggregation mapping on cancel', () => {
-    formComponent.getCancelButton().click();
+    form.getCancelButton().click();
 
-    exist(component.getWeitereFelderAuswertenButton());
+    exist(page.getWeitereFelderAuswertenButton());
   });
 
   it('should add data field in form', () => {
-    component.getWeitereFelderAuswertenButton().click();
-    formComponent.getAddFieldButton().click();
+    page.getWeitereFelderAuswertenButton().click();
+    form.getAddFieldButton().click();
 
-    exist(formComponent.getDataFieldInput(1));
+    exist(form.getDataFieldInput(1));
   });
 
   it('should fill out form with two data fields', () => {
-    helper.enterForm(aggregationMapping);
+    helper.fillFormular(aggregationMapping);
 
-    helper.verifyForm(aggregationMapping);
+    verifier.verifyForm(aggregationMapping);
   });
 
   it('should delete data fields', () => {
-    formComponent.getDataFieldDeleteButton(0).click();
+    form.getDataFieldDeleteButton(0).click();
 
-    notExist(formComponent.getDataFieldInput(1));
+    notExist(form.getDataFieldInput(1));
   });
 
   it('should show aggregation mapping in list after save', () => {
-    formComponent.getSaveButton().click();
+    form.getSaveButton().click();
 
-    helper.verifyAggregationMappingInList(aggregationMapping);
+    verifier.verifyAggregationMappingInList(aggregationMapping);
   });
 });
diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.executor.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.executor.ts
new file mode 100644
index 0000000000..7e9b392696
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.executor.ts
@@ -0,0 +1,22 @@
+import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared';
+import { AggregationMappingFormE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping-form.e2e.component';
+import { enterWith } from '../../support/cypress.util';
+
+export class E2EAggregationMappingExecutor {
+  private formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
+
+  public fillFormular(aggregationMapping: AggregationMapping): void {
+    enterWith(this.formComponent.getNameInput(), aggregationMapping.name);
+    enterWith(this.formComponent.getFormEngineInput(), aggregationMapping.formIdentifier.formEngineName);
+    enterWith(this.formComponent.getFormIdInput(), aggregationMapping.formIdentifier.formId);
+
+    aggregationMapping.mappings.forEach((fieldMapping, index) => {
+      this.enterFieldMapping(fieldMapping, index);
+    });
+  }
+
+  private enterFieldMapping(fieldMapping: FieldMapping, index: number): void {
+    enterWith(this.formComponent.getSourceMappingFieldInput(index), fieldMapping.sourcePath);
+    enterWith(this.formComponent.getTargetMappingFieldInput(index), fieldMapping.targetPath);
+  }
+}
diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts
index b36249dc2f..b39a391240 100644
--- a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts
+++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts
@@ -1,65 +1,16 @@
-import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared';
-import { AggregationMappingFormE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping-form.e2e.component';
-import { AggregationMappingE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping.e2e.component';
-import { enterWith, haveText, haveValue } from '../../support/cypress.util';
+import { AggregationMapping } from '@admin-client/reporting-shared';
+import { E2EAggregationMappingExecutor } from './aggregation-mapping.executor';
+import { E2EAggregationMapperNavigator } from './aggregation-mapping.navigator';
 
 export class E2EAggregationMappingHelper {
-  private component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
-  private formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
+  private readonly navigator: E2EAggregationMapperNavigator = new E2EAggregationMapperNavigator();
+  private readonly executor: E2EAggregationMappingExecutor = new E2EAggregationMappingExecutor();
 
-  public enterName(text: string): void {
-    enterWith(this.formComponent.getNameInput(), text);
+  public openStatistik(): void {
+    this.navigator.openStatistik();
   }
 
-  public enterFormEngine(text: string): void {
-    enterWith(this.formComponent.getFormEngineInput(), text);
-  }
-
-  public enterFormId(text: string): void {
-    enterWith(this.formComponent.getFormIdInput(), text);
-  }
-
-  public enterSourcePath(text: string, index: number): void {
-    enterWith(this.formComponent.getSourceMappingFieldInput(index), text);
-  }
-
-  public enterTargetPath(text: string, index: number): void {
-    enterWith(this.formComponent.getTargetMappingFieldInput(index), text);
-  }
-
-  public enterFieldMapping(fieldMapping: FieldMapping, index: number): void {
-    this.enterSourcePath(fieldMapping.sourcePath, index);
-    this.enterTargetPath(fieldMapping.targetPath, index);
-  }
-
-  public enterForm(aggregationMapping: AggregationMapping): void {
-    this.enterName(aggregationMapping.name);
-    this.enterFormEngine(aggregationMapping.formIdentifier.formEngineName);
-    this.enterFormId(aggregationMapping.formIdentifier.formId);
-
-    aggregationMapping.mappings.forEach((fieldMapping, index) => {
-      this.enterFieldMapping(fieldMapping, index);
-    });
-  }
-
-  public verifyFieldMapping(fieldMapping: FieldMapping, index: number): void {
-    haveValue(this.formComponent.getSourceMappingFieldInput(index), fieldMapping.sourcePath);
-    haveValue(this.formComponent.getTargetMappingFieldInput(index), fieldMapping.targetPath);
-  }
-
-  public verifyForm(aggregationMapping: AggregationMapping): void {
-    haveValue(this.formComponent.getNameInput(), aggregationMapping.name);
-    haveValue(this.formComponent.getFormEngineInput(), aggregationMapping.formIdentifier.formEngineName);
-    haveValue(this.formComponent.getFormIdInput(), aggregationMapping.formIdentifier.formId);
-
-    aggregationMapping.mappings.forEach((fieldMapping, index) => {
-      this.verifyFieldMapping(fieldMapping, index);
-    });
-  }
-
-  public verifyAggregationMappingInList(aggregationMapping: AggregationMapping): void {
-    haveText(this.component.getListItemName(), aggregationMapping.name);
-    haveText(this.component.getListItemFormEngineName(), aggregationMapping.formIdentifier.formEngineName);
-    haveText(this.component.getListItemFormId(), aggregationMapping.formIdentifier.formId);
+  public fillFormular(aggregationMapping: AggregationMapping): void {
+    this.executor.fillFormular(aggregationMapping);
   }
 }
diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.navigator.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.navigator.ts
new file mode 100644
index 0000000000..f82cc54792
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.navigator.ts
@@ -0,0 +1,18 @@
+import { AggregationMappingE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping.e2e.component';
+import { MainPage } from '../../page-objects/main.po';
+import { exist } from '../../support/cypress.util';
+import { E2EAppHelper } from '../app.helper';
+
+export class E2EAggregationMapperNavigator {
+  private readonly appHelper: E2EAppHelper = new E2EAppHelper();
+
+  private readonly mainPage: MainPage = new MainPage();
+
+  private readonly aggregationMappingPage: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
+
+  public openStatistik(): void {
+    this.appHelper.navigateToDomain();
+    this.mainPage.getStatistikNavigationItem().click();
+    exist(this.aggregationMappingPage.getHeaderText());
+  }
+}
diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier.ts
new file mode 100644
index 0000000000..df93defea4
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier.ts
@@ -0,0 +1,34 @@
+import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared';
+import { AggregationMappingFormE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping-form.e2e.component';
+import {
+  AggregationMappingE2EComponent,
+  AggregationMappingListItemE2EComponent,
+} from '../../components/aggregation-mapping/aggregation-mapping.e2e.component';
+import { haveText, haveValue } from '../../support/cypress.util';
+
+export class E2EAggregationMappingVerifier {
+  private component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent();
+  private formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent();
+
+  public verifyFieldMapping(fieldMapping: FieldMapping, index: number): void {
+    haveValue(this.formComponent.getSourceMappingFieldInput(index), fieldMapping.sourcePath);
+    haveValue(this.formComponent.getTargetMappingFieldInput(index), fieldMapping.targetPath);
+  }
+
+  public verifyForm(aggregationMapping: AggregationMapping): void {
+    haveValue(this.formComponent.getNameInput(), aggregationMapping.name);
+    haveValue(this.formComponent.getFormEngineInput(), aggregationMapping.formIdentifier.formEngineName);
+    haveValue(this.formComponent.getFormIdInput(), aggregationMapping.formIdentifier.formId);
+
+    aggregationMapping.mappings.forEach((fieldMapping, index) => {
+      this.verifyFieldMapping(fieldMapping, index);
+    });
+  }
+
+  public verifyAggregationMappingInList(aggregationMapping: AggregationMapping): void {
+    const listItem: AggregationMappingListItemE2EComponent = this.component.getListItem(aggregationMapping.name);
+    haveText(listItem.getName(), aggregationMapping.name);
+    haveText(listItem.getFormEngineName(), aggregationMapping.formIdentifier.formEngineName);
+    haveText(listItem.getFormId(), aggregationMapping.formIdentifier.formId);
+  }
+}
diff --git a/alfa-client/apps/admin-e2e/src/helper/app.helper.ts b/alfa-client/apps/admin-e2e/src/helper/app.helper.ts
new file mode 100644
index 0000000000..ee3170e548
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/helper/app.helper.ts
@@ -0,0 +1,9 @@
+import { MainPage } from '../page-objects/main.po';
+
+export class E2EAppHelper {
+  private readonly mainPage: MainPage = new MainPage();
+
+  public navigateToDomain(): void {
+    this.mainPage.getHeader().getLogo().click();
+  }
+}
diff --git a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
index 75ecbdaefa..c982465ac9 100644
--- a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
+++ b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
@@ -31,7 +31,7 @@ export class MainPage {
   private readonly benutzerNavigationItem: string = 'link-path-benutzer';
   private readonly organisationEinheitNavigationItem: string = 'link-path-organisationseinheiten';
   private readonly postfachNavigationItem: string = 'link-path-postfach';
-  private readonly statistikNavigationItem: string = 'link-path-statistik';
+  private readonly statistikNavigationItem: string = 'link-path-aggregation-mapping';
 
   public getBuildInfo(): BuildInfoE2EComponent {
     return this.buildInfo;
diff --git a/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts b/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts
index 83e7bb11f0..5d457ea558 100644
--- a/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts
+++ b/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts
@@ -21,6 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { HttpMethod } from '@alfa-client/tech-shared';
 import { Interception, RouteHandler, RouteMatcher } from 'cypress/types/net-stubbing';
 import { OrganisationsEinheitE2E } from './organisationseinheit';
 
@@ -31,7 +32,7 @@ enum CypressTasks {
 
 enum MongoCollections {
   ORGANISATIONS_EINHEIT = 'organisationsEinheit',
-  SETTINGS = 'settings',
+  AGGREGATION_MAPPING = 'aggregationMapping',
 }
 
 const DOWNLOAD_FOLDER: string = 'cypress/downloads';
@@ -48,7 +49,7 @@ export function intercept(method: string, url: string): Cypress.Chainable<null>
   return cy.intercept(method, url);
 }
 
-export function interceptWithResponse(method, url: RouteMatcher, response: RouteHandler): Cypress.Chainable<null> {
+export function interceptWithResponse(method: HttpMethod, url: RouteMatcher, response: RouteHandler): Cypress.Chainable<null> {
   return cy.intercept(method, url, response);
 }
 
@@ -110,6 +111,5 @@ export function initOrganisationsEinheitenData(data: OrganisationsEinheitE2E[]):
 }
 
 export function dropCollections() {
-  cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.ORGANISATIONS_EINHEIT]);
-  cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.SETTINGS]);
+  cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.ORGANISATIONS_EINHEIT, MongoCollections.AGGREGATION_MAPPING]);
 }
-- 
GitLab


From 09e0dbb3508c91625c3727fc9fb6af97f54f392b Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 11:08:00 +0100
Subject: [PATCH 22/47] OZG-7473 make data test ids unique

Based on CR comment.
---
 .../aggregation-mapping-form.component.html                   | 4 ++--
 .../aggregation-mapping-form.component.spec.ts                | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
index b69813d98a..346b7322dd 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.html
@@ -21,7 +21,7 @@
           label="Formengine"
           placeholder="Tragen Sie hier die Formengine des Formulars ein."
           isRequired="true"
-          data-test-id="form-engine-name"
+          data-test-id="form-engine-name-text-editor"
           dataTestId="form-engine-name"
         ></ods-text-editor>
         <ods-text-editor
@@ -30,7 +30,7 @@
           label="FormID"
           placeholder="Tragen Sie hier die FormID des Formulars ein."
           isRequired="true"
-          data-test-id="form-id"
+          data-test-id="form-id-text-editor"
           dataTestId="form-id"
         ></ods-text-editor>
       </div>
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
index e6a2b6989c..30708be6ae 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
@@ -27,8 +27,8 @@ describe('AggregationMappingFormComponent', () => {
   let component: AggregationMappingFormComponent;
   let fixture: ComponentFixture<AggregationMappingFormComponent>;
 
-  const formEngineNameInputTestId: string = getDataTestIdOf('form-engine-name');
-  const formIdInputTestId: string = getDataTestIdOf('form-id');
+  const formEngineNameInputTestId: string = getDataTestIdOf('form-engine-name-text-editor');
+  const formIdInputTestId: string = getDataTestIdOf('form-id-text-editor');
   const addMappingButton: string = getDataTestIdOf('add-mapping');
 
   const aggregationMappingStateResource: StateResource<AggregationMappingResource> = createStateResource(
-- 
GitLab


From 11fa4e1840218a7f1002570bc458647317a3f467 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 11:11:48 +0100
Subject: [PATCH 23/47] OZG-7473 improve tests

Based on CR comment.
---
 .../aggregation-mapping-list.component.spec.ts       | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
index c632c4a20b..9500dffc91 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
@@ -50,7 +50,7 @@ describe('AggregationMappingListComponent', () => {
       expect(component.aggregationMappings).toEqual([]);
     });
 
-    describe('_update', () => {
+    describe('update', () => {
       it('should set list state resource', () => {
         component.aggregationMappingListStateResource = aggregationMappingListStateResource;
 
@@ -99,18 +99,16 @@ describe('AggregationMappingListComponent', () => {
       fixture.detectChanges();
     });
 
+    it('should have list', () => {
+      expectComponentExistsInTemplate(fixture, ListComponent);
+    });
+
     it('should have spinner with state resource', () => {
-      expectComponentExistsInTemplate(fixture, SpinnerComponent);
       const comp = getElementFromFixtureByType(fixture, SpinnerComponent);
       expect(comp.stateResource).toEqual(aggregationMappingListStateResource);
     });
 
-    it('should have list', () => {
-      expectComponentExistsInTemplate(fixture, ListComponent);
-    });
-
     it('should have list item with mapping', () => {
-      expectComponentExistsInTemplate(fixture, AggregationMappingListItemComponent);
       const comp = getElementFromFixtureByType(fixture, AggregationMappingListItemComponent);
       expect(comp.aggregationMapping).toEqual(
         getEmbeddedResources(aggregationMappingListStateResource, AggregationMappingListLinkRel.LIST)[0],
-- 
GitLab


From 86a9a26975d5d555121cf8260d636dc2b12c6b63 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 18:35:33 +0100
Subject: [PATCH 24/47] OZG-7473 extract method

Based on CR comment.
---
 .../admin-save-button.component.spec.ts       | 62 ++++++++++++-------
 .../admin-save-button.component.ts            | 12 ++--
 2 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
index 1d3a06aa4f..d6ff6dfa2d 100644
--- a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
+++ b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
@@ -1,6 +1,6 @@
 import { ADMIN_FORMSERVICE } from '@admin-client/shared';
 import { NavigationService } from '@alfa-client/navigation-shared';
-import { AbstractFormService, createStateResource, isValidStateResource, StateResource } from '@alfa-client/tech-shared';
+import { AbstractFormService, createStateResource, isLoaded, StateResource } from '@alfa-client/tech-shared';
 import { dispatchEventFromFixture, getMockComponent, mock, Mock, MockEvent } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { faker } from '@faker-js/faker/.';
@@ -17,10 +17,10 @@ import { AdminSaveButtonComponent } from './admin-save-button.component';
 jest.mock('@alfa-client/tech-shared', () => {
   return {
     ...jest.requireActual('@alfa-client/tech-shared'),
-    isValidStateResource: jest.fn(),
+    isLoaded: jest.fn(),
   };
 });
-const isValidStateResourceMock: jest.Mock = isValidStateResource as jest.Mock;
+const isLoadedMock: jest.Mock = isLoaded as jest.Mock;
 
 describe('AdminSaveButtonComponent', () => {
   let component: AdminSaveButtonComponent;
@@ -61,36 +61,50 @@ describe('AdminSaveButtonComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  describe('on submit', () => {
-    it('should call formService', () => {
-      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+  describe('component', () => {
+    describe('on successful form submission', () => {
+      it('should navigate to success link path', () => {
+        const successLinkPath: string = faker.internet.url();
+        component.successLinkPath = successLinkPath;
+        isLoadedMock.mockReturnValue(true);
 
-      expect(formService.submit).toHaveBeenCalled();
-    });
+        component._navigateOnSuccessfulSubmission(createStateResource(createDummyResource()));
+
+        expect(navigationService.navigate).toHaveBeenCalledWith(successLinkPath);
+      });
+
+      it('should NOT navigate', () => {
+        isLoadedMock.mockReturnValue(false);
 
-    it('should assign state resource', () => {
-      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+        component._navigateOnSuccessfulSubmission(createStateResource(createDummyResource()));
 
-      expect(component.stateResource$).toBeObservable(singleColdCompleted(stateResource));
+        expect(navigationService.navigate).not.toHaveBeenCalled();
+      });
     });
 
-    it('should navigate on successful submit', () => {
-      isValidStateResourceMock.mockReturnValue(true);
-      const linkPath: string = faker.internet.url();
-      component.successLinkPath = linkPath;
+    describe('on submit', () => {
+      beforeEach(() => {
+        component._navigateOnSuccessfulSubmission = jest.fn();
+      });
 
-      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
-      component.stateResource$.subscribe();
+      it('should call formService', () => {
+        dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
 
-      expect(navigationService.navigate).toHaveBeenCalledWith(linkPath);
-    });
+        expect(formService.submit).toHaveBeenCalled();
+      });
+
+      it('should assign state resource', () => {
+        dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+
+        expect(component.stateResource$).toBeObservable(singleColdCompleted(stateResource));
+      });
 
-    it('should NOT navigate on invalid state resource', () => {
-      isValidStateResourceMock.mockReturnValue(false);
-      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
-      component.stateResource$.subscribe();
+      it('should navigate on successful submit', () => {
+        dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+        component.stateResource$.subscribe();
 
-      expect(navigationService.navigate).not.toHaveBeenCalled();
+        expect(component._navigateOnSuccessfulSubmission).toHaveBeenCalledWith(stateResource);
+      });
     });
   });
 
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
index 7f0ff88dcd..598d056ea6 100644
--- a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
+++ b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
@@ -1,6 +1,6 @@
 import { ADMIN_FORMSERVICE } from '@admin-client/shared';
 import { NavigationService } from '@alfa-client/navigation-shared';
-import { AbstractFormService, createEmptyStateResource, isValidStateResource, StateResource } from '@alfa-client/tech-shared';
+import { AbstractFormService, createEmptyStateResource, isLoaded, StateResource } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, inject, Input } from '@angular/core';
 import { Resource } from '@ngxp/rest';
@@ -24,10 +24,14 @@ export class AdminSaveButtonComponent {
   public submit(): void {
     this.stateResource$ = this.formService.submit().pipe(
       tap((stateResource: StateResource<Resource>) => {
-        if (isValidStateResource(stateResource)) {
-          this.navigationService.navigate(this.successLinkPath);
-        }
+        this._navigateOnSuccessfulSubmission(stateResource);
       }),
     );
   }
+
+  _navigateOnSuccessfulSubmission(stateResource: StateResource<Resource>) {
+    if (isLoaded(stateResource)) {
+      this.navigationService.navigate(this.successLinkPath);
+    }
+  }
 }
-- 
GitLab


From 82897c2dc6f29a86eb3797e5591f2aed86b5cde2 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 18:47:45 +0100
Subject: [PATCH 25/47] OZG-7473 rename route

Based on CR comment.
---
 alfa-client/apps/admin/src/app/app.component.spec.ts | 2 +-
 alfa-client/libs/admin/shared/src/lib/routes.ts      | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts
index cc45121d96..3c1142c2c7 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -297,7 +297,7 @@ describe('AppComponent', () => {
       it('should navigate to statistik if aggregation mapping link exists', () => {
         component._navigateByConfiguration(createConfigurationResource([ConfigurationLinkRel.AGGREGATION_MAPPINGS]));
 
-        expect(router.navigate).toHaveBeenCalledWith(['/aggregation-mapping']);
+        expect(router.navigate).toHaveBeenCalledWith(['/auswertung']);
       });
 
       it('should navigate to unavailable page if no link exists', () => {
diff --git a/alfa-client/libs/admin/shared/src/lib/routes.ts b/alfa-client/libs/admin/shared/src/lib/routes.ts
index cf1a221202..6802911d70 100644
--- a/alfa-client/libs/admin/shared/src/lib/routes.ts
+++ b/alfa-client/libs/admin/shared/src/lib/routes.ts
@@ -28,7 +28,7 @@ export enum ROUTES {
   BENUTZER_ID = 'benutzer/:userid',
   ORGANISATIONSEINHEITEN = 'organisationseinheiten',
   UNAVAILABLE = 'unavailable',
-  AGGREGATION_MAPPING = 'aggregation-mapping',
-  AGGREGATION_MAPPING_NEU = 'aggregation-mapping/neu',
-  AGGREGATION_MAPPING_ID = 'aggregation-mapping/:aggregationMappingId',
+  AGGREGATION_MAPPING = 'auswertung',
+  AGGREGATION_MAPPING_NEU = 'auswertung/neu',
+  AGGREGATION_MAPPING_ID = 'auswertung/:aggregationMappingId',
 }
-- 
GitLab


From a85c860723fcee8bb553d5bed81a5c31bb387a03 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 18:49:04 +0100
Subject: [PATCH 26/47] OZG-7473 change route title

Based on CR comment.
---
 alfa-client/apps/admin/src/app/app.routes.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/alfa-client/apps/admin/src/app/app.routes.ts b/alfa-client/apps/admin/src/app/app.routes.ts
index 25576ae40b..dcdc28a4fd 100644
--- a/alfa-client/apps/admin/src/app/app.routes.ts
+++ b/alfa-client/apps/admin/src/app/app.routes.ts
@@ -93,7 +93,7 @@ export const appRoutes: Route[] = [
   {
     path: ROUTES.AGGREGATION_MAPPING_NEU,
     component: AggregationMappingFormPageComponent,
-    title: 'Admin | Statistik weitere Felder auswerten',
+    title: 'Admin | Auswertung anlegen',
     runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
     data: <GuardData>{ linkRelName: ConfigurationLinkRel.AGGREGATION_MAPPINGS },
@@ -101,7 +101,7 @@ export const appRoutes: Route[] = [
   {
     path: ROUTES.AGGREGATION_MAPPING_ID,
     component: AggregationMappingFormPageComponent,
-    title: 'Admin | Statistik weitere Felder auswerten',
+    title: 'Admin | Auswertung bearbeiten',
     runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
     data: <GuardData>{ linkRelName: ConfigurationLinkRel.AGGREGATION_MAPPINGS },
-- 
GitLab


From 75db18a025e3cc29b4e05493ff7f182ebeac611f Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 18:50:14 +0100
Subject: [PATCH 27/47] OZG-7473 use const from form service

Based on CR comment.
---
 .../aggregation-mapping-field-form.component.html             | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
index 8469852f2b..a70383f4bc 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.html
@@ -18,7 +18,7 @@
         </div>
         <div class="flex flex-col gap-4">
           <ods-text-editor
-            formControlName="sourcePath"
+            [formControlName]="AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH"
             label="Pfad"
             placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
             isRequired="true"
@@ -26,7 +26,7 @@
             [attr.data-test-id]="'source-mapping-field-' + index"
           ></ods-text-editor>
           <ods-text-editor
-            formControlName="targetPath"
+            [formControlName]="AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH"
             label="Zielfeld"
             isRequired="true"
             placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
-- 
GitLab


From 17439bc937ccefc6122c5f38d1484b0d3962b887 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 18:51:55 +0100
Subject: [PATCH 28/47] OZG-7473 replace string with const

Based on CR comment.
---
 .../aggregation-mapping-field-form.component.spec.ts          | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
index cd207241e7..a1f28ea1c6 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
@@ -1,6 +1,6 @@
 import { ADMIN_FORMSERVICE } from '@admin-client/shared';
 import { EMPTY_STRING } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, mock, Mock, mockGetValue, triggerEvent } from '@alfa-client/test-utils';
+import { existsAsHtmlElement, mock, Mock, MockEvent, mockGetValue, triggerEvent } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
 import { expect } from '@jest/globals';
@@ -78,7 +78,7 @@ describe('AggregationMappingFieldFormComponent', () => {
       });
 
       it('should remove mapping on click', () => {
-        triggerEvent({ fixture, elementSelector: removeMappingButtonTestId, name: 'clickEmitter', data: fieldIndex });
+        triggerEvent({ fixture, elementSelector: removeMappingButtonTestId, name: MockEvent.CLICK, data: fieldIndex });
 
         expect(formService.removeMapping).toHaveBeenCalledWith(fieldIndex);
       });
-- 
GitLab


From 221ecd1c1dac654e68b1efda8cc56f4db9e2140b Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 18:57:05 +0100
Subject: [PATCH 29/47] OZG-7473 use getter and rename file

Based on CR comment.
---
 ...ation-mapping-field-form.component.spec.ts | 16 +++++-----
 ...ggregation-mapping-field-form.component.ts |  6 ++--
 ...-mapping-field-list-form.component.spec.ts | 16 +++++-----
 ...ation-mapping-field-list-form.component.ts |  6 ++--
 ...aggregation-mapping-form.component.spec.ts | 16 +++++-----
 .../aggregation-mapping-form.component.ts     |  8 ++---
 .../aggregation-mapping.formservice.spec.ts   | 30 +++++++++----------
 ....ts => aggregation-mapping.formservice.ts} | 20 ++++++-------
 8 files changed, 59 insertions(+), 59 deletions(-)
 rename alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/{aggregation-mapping-form.service.ts => aggregation-mapping.formservice.ts} (78%)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
index a1f28ea1c6..d5f466dd45 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.spec.ts
@@ -8,7 +8,7 @@ import { TextEditorComponent } from '@ods/component';
 import { ButtonComponent, DeleteIconComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
 import { getDataTestIdOf } from '../../../../../../../../tech-shared/test/data-test';
-import { AggregationMappingFormService } from '../../aggregation-mapping-form.service';
+import { AggregationMappingFormservice } from '../../aggregation-mapping.formservice';
 import { AggregationMappingFieldFormComponent } from './aggregation-mapping-field-form.component';
 
 describe('AggregationMappingFieldFormComponent', () => {
@@ -21,20 +21,20 @@ describe('AggregationMappingFieldFormComponent', () => {
   const targetPathEditorTestId: string = getDataTestIdOf('target-mapping-field-0');
   const removeMappingButtonTestId: string = getDataTestIdOf('remove-mapping-0');
 
-  let formService: Mock<AggregationMappingFormService>;
+  let formService: Mock<AggregationMappingFormservice>;
 
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
-      [AggregationMappingFormService.FIELD_MAPPINGS]: formBuilder.array([
+      [AggregationMappingFormservice.FIELD_MAPPINGS]: formBuilder.array([
         new FormGroup({
-          [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
-          [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormservice.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormservice.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
         }),
       ]),
     });
 
     formService = <any>{
-      ...mock(AggregationMappingFormService),
+      ...mock(AggregationMappingFormservice),
       form,
       addMapping: jest.fn(),
       removeMapping: jest.fn(),
@@ -42,8 +42,8 @@ describe('AggregationMappingFieldFormComponent', () => {
 
     mockGetValue(
       formService,
-      AggregationMappingFormService.FIELD_MAPPINGS,
-      form.controls[AggregationMappingFormService.FIELD_MAPPINGS],
+      AggregationMappingFormservice.FIELD_MAPPINGS,
+      form.controls[AggregationMappingFormservice.FIELD_MAPPINGS],
     );
 
     await TestBed.configureTestingModule({
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
index d7e2e1f162..346d5f2704 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-form/aggregation-mapping-field-form.component.ts
@@ -3,7 +3,7 @@ import { Component, inject, Input } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { TextEditorComponent } from '@ods/component';
 import { ButtonComponent, DeleteIconComponent } from '@ods/system';
-import { AggregationMappingFormService } from '../../aggregation-mapping-form.service';
+import { AggregationMappingFormservice } from '../../aggregation-mapping.formservice';
 
 @Component({
   selector: 'admin-aggregation-mapping-field-form',
@@ -14,7 +14,7 @@ import { AggregationMappingFormService } from '../../aggregation-mapping-form.se
 export class AggregationMappingFieldFormComponent {
   @Input({ required: true }) index: number;
 
-  public readonly formService = <AggregationMappingFormService>inject(ADMIN_FORMSERVICE);
+  public readonly formService = <AggregationMappingFormservice>inject(ADMIN_FORMSERVICE);
 
-  public readonly AggregationMappingFormService = AggregationMappingFormService;
+  public readonly AggregationMappingFormService = AggregationMappingFormservice;
 }
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts
index 345f9cbf24..724a1e08cc 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.spec.ts
@@ -6,7 +6,7 @@ import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angul
 import { expect } from '@jest/globals';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
-import { AggregationMappingFormService } from '../aggregation-mapping-form.service';
+import { AggregationMappingFormservice } from '../aggregation-mapping.formservice';
 import { AggregationMappingFieldFormComponent } from './aggregation-mapping-field-form/aggregation-mapping-field-form.component';
 import { AggregationMappingFieldListFormComponent } from './aggregation-mapping-field-list-form.component';
 
@@ -18,20 +18,20 @@ describe('AggregationMappingFieldListFormComponent', () => {
 
   const formBuilder: FormBuilder = new FormBuilder();
 
-  let formService: Mock<AggregationMappingFormService>;
+  let formService: Mock<AggregationMappingFormservice>;
 
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
-      [AggregationMappingFormService.FIELD_MAPPINGS]: formBuilder.array([
+      [AggregationMappingFormservice.FIELD_MAPPINGS]: formBuilder.array([
         new FormGroup({
-          [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
-          [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormservice.FIELD_MAPPING_SOURCE_PATH]: new FormControl(EMPTY_STRING),
+          [AggregationMappingFormservice.FIELD_MAPPING_TARGET_PATH]: new FormControl(EMPTY_STRING),
         }),
       ]),
     });
 
     formService = <any>{
-      ...mock(AggregationMappingFormService),
+      ...mock(AggregationMappingFormservice),
       form,
       addMapping: jest.fn(),
       removeMapping: jest.fn(),
@@ -39,8 +39,8 @@ describe('AggregationMappingFieldListFormComponent', () => {
 
     mockGetValue(
       formService,
-      AggregationMappingFormService.FIELD_MAPPINGS,
-      form.controls[AggregationMappingFormService.FIELD_MAPPINGS],
+      AggregationMappingFormservice.FIELD_MAPPINGS,
+      form.controls[AggregationMappingFormservice.FIELD_MAPPINGS],
     );
 
     await TestBed.configureTestingModule({
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts
index 2adaffcbef..7b751ad914 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.ts
@@ -2,7 +2,7 @@ import { ADMIN_FORMSERVICE } from '@admin-client/shared';
 import { CommonModule } from '@angular/common';
 import { Component, inject } from '@angular/core';
 import { AbstractControl, ReactiveFormsModule } from '@angular/forms';
-import { AggregationMappingFormService } from '../aggregation-mapping-form.service';
+import { AggregationMappingFormservice } from '../aggregation-mapping.formservice';
 import { AggregationMappingFieldFormComponent } from './aggregation-mapping-field-form/aggregation-mapping-field-form.component';
 
 @Component({
@@ -12,9 +12,9 @@ import { AggregationMappingFieldFormComponent } from './aggregation-mapping-fiel
   imports: [CommonModule, ReactiveFormsModule, AggregationMappingFieldFormComponent],
 })
 export class AggregationMappingFieldListFormComponent {
-  public readonly formService = <AggregationMappingFormService>inject(ADMIN_FORMSERVICE);
+  public readonly formService = <AggregationMappingFormservice>inject(ADMIN_FORMSERVICE);
 
   public readonly mappingsFormArray: AbstractControl[] = this.formService.mappings.controls;
 
-  public readonly AggregationMappingFormService = AggregationMappingFormService;
+  public readonly AggregationMappingFormService = AggregationMappingFormservice;
 }
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
index 30708be6ae..2abba71105 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.spec.ts
@@ -21,7 +21,7 @@ import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles'
 import { createAggregationMappingResource } from '../../../../../reporting-shared/test/aggregation-mapping';
 import { AggregationMappingFieldListFormComponent } from './aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component';
 import { AggregationMappingFormComponent } from './aggregation-mapping-form.component';
-import { AggregationMappingFormService } from './aggregation-mapping-form.service';
+import { AggregationMappingFormservice } from './aggregation-mapping.formservice';
 
 describe('AggregationMappingFormComponent', () => {
   let component: AggregationMappingFormComponent;
@@ -37,18 +37,18 @@ describe('AggregationMappingFormComponent', () => {
 
   const formBuilder: FormBuilder = new FormBuilder();
 
-  let formService: Mock<AggregationMappingFormService>;
+  let formService: Mock<AggregationMappingFormservice>;
 
   beforeEach(async () => {
     const form: FormGroup = formBuilder.group({
-      [AggregationMappingFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
-      [AggregationMappingFormService.FIELD_FORM_IDENTIFIER]: formBuilder.group({
-        [AggregationMappingFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
-        [AggregationMappingFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormservice.FIELD_NAME]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormservice.FIELD_FORM_IDENTIFIER]: formBuilder.group({
+        [AggregationMappingFormservice.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
+        [AggregationMappingFormservice.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
       }),
     });
 
-    formService = <any>{ ...mock(AggregationMappingFormService), form };
+    formService = <any>{ ...mock(AggregationMappingFormservice), form };
     formService.get = jest.fn().mockReturnValue(of(aggregationMappingStateResource));
 
     await TestBed.configureTestingModule({
@@ -67,7 +67,7 @@ describe('AggregationMappingFormComponent', () => {
         set: {
           providers: [
             {
-              provide: AggregationMappingFormService,
+              provide: AggregationMappingFormservice,
               useValue: formService,
             },
             {
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts
index d113a410a3..4865e55212 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.component.ts
@@ -8,7 +8,7 @@ import { SpinnerComponent, TextEditorComponent } from '@ods/component';
 import { ButtonComponent, PlusIconComponent } from '@ods/system';
 import { Observable } from 'rxjs';
 import { AggregationMappingFieldListFormComponent } from './aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component';
-import { AggregationMappingFormService } from './aggregation-mapping-form.service';
+import { AggregationMappingFormservice } from './aggregation-mapping.formservice';
 
 @Component({
   selector: 'admin-aggregation-mapping-form',
@@ -25,14 +25,14 @@ import { AggregationMappingFormService } from './aggregation-mapping-form.servic
     AsyncPipe,
     TextEditorComponent,
   ],
-  providers: [{ provide: ADMIN_FORMSERVICE, useClass: AggregationMappingFormService }],
+  providers: [{ provide: ADMIN_FORMSERVICE, useClass: AggregationMappingFormservice }],
 })
 export class AggregationMappingFormComponent {
-  public readonly formService = <AggregationMappingFormService>inject(ADMIN_FORMSERVICE);
+  public readonly formService = <AggregationMappingFormservice>inject(ADMIN_FORMSERVICE);
 
   public readonly aggregationMappingStateResource$: Observable<StateResource<AggregationMappingResource>> =
     this.formService.get();
 
-  public readonly AggregationMappingFormService = AggregationMappingFormService;
+  public readonly AggregationMappingFormService = AggregationMappingFormservice;
   public readonly Routes = ROUTES;
 }
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
index fab98f538a..72ad99b1cc 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
@@ -31,10 +31,10 @@ import { createAggregationMapping, createAggregationMappingResource } from 'libs
 import { omit } from 'lodash-es';
 import { of } from 'rxjs';
 import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
-import { AggregationMappingFormService } from './aggregation-mapping-form.service';
+import { AggregationMappingFormservice } from './aggregation-mapping.formservice';
 
 describe('AggregationMappingFormService', () => {
-  let formService: AggregationMappingFormService;
+  let formService: AggregationMappingFormservice;
 
   let service: Mock<AggregationMappingService>;
 
@@ -42,10 +42,10 @@ describe('AggregationMappingFormService', () => {
     service = mock(AggregationMappingService);
 
     TestBed.configureTestingModule({
-      providers: [AggregationMappingFormService, { provide: AggregationMappingService, useValue: service }],
+      providers: [AggregationMappingFormservice, { provide: AggregationMappingService, useValue: service }],
     });
 
-    formService = TestBed.inject(AggregationMappingFormService);
+    formService = TestBed.inject(AggregationMappingFormservice);
   });
 
   it('should create', () => {
@@ -83,31 +83,31 @@ describe('AggregationMappingFormService', () => {
     it('should add mapping control', () => {
       formService.addMapping();
 
-      const mappingFormArray: FormArray = <FormArray>formService.form.controls[AggregationMappingFormService.FIELD_MAPPINGS];
+      const mappingFormArray: FormArray = <FormArray>formService.form.controls[AggregationMappingFormservice.FIELD_MAPPINGS];
       expect(mappingFormArray).toHaveLength(2);
       expect(mappingFormArray.controls[0].value).toEqual({
-        [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
-        [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+        [AggregationMappingFormservice.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [AggregationMappingFormservice.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
       });
     });
   });
 
   describe('remove mapping', () => {
     it('should remove mapping control', () => {
-      (<FormArray>formService.form.controls[AggregationMappingFormService.FIELD_MAPPINGS]).push(
+      (<FormArray>formService.form.controls[AggregationMappingFormservice.FIELD_MAPPINGS]).push(
         new FormGroup({
-          [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl('controlToRemove'),
-          [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl('controlToRemove'),
+          [AggregationMappingFormservice.FIELD_MAPPING_SOURCE_PATH]: new FormControl('controlToRemove'),
+          [AggregationMappingFormservice.FIELD_MAPPING_TARGET_PATH]: new FormControl('controlToRemove'),
         }),
       );
 
       formService.removeMapping(1);
 
-      const mappingFormArray: FormArray = <FormArray>formService.form.controls[AggregationMappingFormService.FIELD_MAPPINGS];
+      const mappingFormArray: FormArray = <FormArray>formService.form.controls[AggregationMappingFormservice.FIELD_MAPPINGS];
       expect(mappingFormArray).toHaveLength(1);
       expect(mappingFormArray.controls[0].value).toEqual({
-        [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
-        [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+        [AggregationMappingFormservice.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [AggregationMappingFormservice.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
       });
     });
   });
@@ -118,8 +118,8 @@ describe('AggregationMappingFormService', () => {
 
       expect(mappings).toHaveLength(1);
       expect(mappings.controls[0].value).toEqual({
-        [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
-        [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
+        [AggregationMappingFormservice.FIELD_MAPPING_SOURCE_PATH]: EMPTY_STRING,
+        [AggregationMappingFormservice.FIELD_MAPPING_TARGET_PATH]: EMPTY_STRING,
       });
     });
   });
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.service.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.ts
similarity index 78%
rename from alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.service.ts
rename to alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.ts
index 664ed43622..3096bf7854 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-form.service.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.ts
@@ -5,7 +5,7 @@ import { FormArray, FormControl, FormGroup, UntypedFormGroup } from '@angular/fo
 import { filter, Observable, tap } from 'rxjs';
 
 @Injectable()
-export class AggregationMappingFormService extends AbstractFormService<AggregationMappingResource> {
+export class AggregationMappingFormservice extends AbstractFormService<AggregationMappingResource> {
   public static readonly FIELD_NAME: string = 'name';
   public static readonly FIELD_FORM_IDENTIFIER: string = 'formIdentifier';
   public static readonly FIELD_FORM_ENGINE_NAME: string = 'formEngineName';
@@ -18,12 +18,12 @@ export class AggregationMappingFormService extends AbstractFormService<Aggregati
 
   protected initForm(): UntypedFormGroup {
     return this.formBuilder.group({
-      [AggregationMappingFormService.FIELD_NAME]: new FormControl(EMPTY_STRING),
-      [AggregationMappingFormService.FIELD_FORM_IDENTIFIER]: this.formBuilder.group({
-        [AggregationMappingFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
-        [AggregationMappingFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormservice.FIELD_NAME]: new FormControl(EMPTY_STRING),
+      [AggregationMappingFormservice.FIELD_FORM_IDENTIFIER]: this.formBuilder.group({
+        [AggregationMappingFormservice.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
+        [AggregationMappingFormservice.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
       }),
-      [AggregationMappingFormService.FIELD_MAPPINGS]: new FormArray([this.createArrayControl()]),
+      [AggregationMappingFormservice.FIELD_MAPPINGS]: new FormArray([this.createArrayControl()]),
     });
   }
 
@@ -44,8 +44,8 @@ export class AggregationMappingFormService extends AbstractFormService<Aggregati
 
   private createArrayControl(sourcePath: string = EMPTY_STRING, targetPath: string = EMPTY_STRING): FormGroup {
     return new FormGroup({
-      [AggregationMappingFormService.FIELD_MAPPING_SOURCE_PATH]: new FormControl(sourcePath),
-      [AggregationMappingFormService.FIELD_MAPPING_TARGET_PATH]: new FormControl(targetPath),
+      [AggregationMappingFormservice.FIELD_MAPPING_SOURCE_PATH]: new FormControl(sourcePath),
+      [AggregationMappingFormservice.FIELD_MAPPING_TARGET_PATH]: new FormControl(targetPath),
     });
   }
 
@@ -54,7 +54,7 @@ export class AggregationMappingFormService extends AbstractFormService<Aggregati
   }
 
   public get mappings(): FormArray {
-    return this.form.controls[AggregationMappingFormService.FIELD_MAPPINGS] as FormArray;
+    return this.form.controls[AggregationMappingFormservice.FIELD_MAPPINGS] as FormArray;
   }
 
   public get(): Observable<StateResource<AggregationMappingResource>> {
@@ -66,7 +66,7 @@ export class AggregationMappingFormService extends AbstractFormService<Aggregati
 
   _patchForm(value: AggregationMappingResource): void {
     this.patch(value);
-    const mappingsFormArray: FormArray = this.form.controls[AggregationMappingFormService.FIELD_MAPPINGS] as FormArray;
+    const mappingsFormArray: FormArray = this.mappings;
     mappingsFormArray.clear();
     value.mappings.forEach((mapping: FieldMapping) =>
       mappingsFormArray.push(this.createArrayControl(mapping.sourcePath, mapping.targetPath)),
-- 
GitLab


From ced17b53c6e28e766fcfff00bec90ed49eca585a Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 18:57:47 +0100
Subject: [PATCH 30/47] OZG-7473 remove null safe check

Based on CR comment.
---
 .../aggregation-mapping-list-item.component.html             | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
index 6b1643e863..9c4788d829 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list-item/aggregation-mapping-list-item.component.html
@@ -4,13 +4,12 @@
       <dt class="sr-only">Name</dt>
       <dd class="font-semibold" data-test-class="list-item-name">{{ aggregationMapping.name }}</dd>
     </div>
-    <!-- Remove null safe check operator after backend provides correct data. -->
     <div class="flex-wrap flex-1">
       <dt class="sr-only">Formengine</dt>
-      <dd data-test-class="list-item-form-engine-name">{{ aggregationMapping.formIdentifier?.formEngineName }}</dd>
+      <dd data-test-class="list-item-form-engine-name">{{ aggregationMapping.formIdentifier.formEngineName }}</dd>
 
       <dt class="sr-only">Form ID</dt>
-      <dd data-test-class="list-item-form-id">{{ aggregationMapping.formIdentifier?.formId }}</dd>
+      <dd data-test-class="list-item-form-id">{{ aggregationMapping.formIdentifier.formId }}</dd>
     </div>
   </dl>
 </ods-list-item>
-- 
GitLab


From b4665ba0810973d33827a413bf428a6fe24cbb6e Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 19:19:51 +0100
Subject: [PATCH 31/47] OZG-7473 get embedded resource in template

Based on CR comment.
---
 .../admin-e2e/src/page-objects/main.po.ts     |  2 +-
 .../aggregation-mapping-list.component.html   |  4 +-
 ...aggregation-mapping-list.component.spec.ts | 58 +------------------
 .../aggregation-mapping-list.component.ts     | 22 ++-----
 4 files changed, 10 insertions(+), 76 deletions(-)

diff --git a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
index c982465ac9..e2b33614a9 100644
--- a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
+++ b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
@@ -31,7 +31,7 @@ export class MainPage {
   private readonly benutzerNavigationItem: string = 'link-path-benutzer';
   private readonly organisationEinheitNavigationItem: string = 'link-path-organisationseinheiten';
   private readonly postfachNavigationItem: string = 'link-path-postfach';
-  private readonly statistikNavigationItem: string = 'link-path-aggregation-mapping';
+  private readonly statistikNavigationItem: string = 'link-path-auswertung';
 
   public getBuildInfo(): BuildInfoE2EComponent {
     return this.buildInfo;
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.html
index 521fc9e92d..fb306dc34f 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.html
@@ -1,6 +1,6 @@
-<ods-spinner [stateResource]="listStateResource">
+<ods-spinner [stateResource]="aggregationMappingListStateResource">
   <ods-list data-test-id="aggregation-mapping-list">
-    @for (aggregationMapping of aggregationMappings; track $index) {
+    @for (aggregationMapping of (aggregationMappingListStateResource.resource | toEmbeddedResources: AggregationMappingListLinkRel.LIST); track $index) {
       <admin-aggregation-mapping-list-item [aggregationMapping]="aggregationMapping" />
     }
   </ods-list>
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
index 9500dffc91..1a6e2d40a4 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
@@ -1,11 +1,5 @@
 import { AggregationMappingListResource } from '@admin-client/reporting-shared';
-import {
-  createEmptyStateResource,
-  createLoadingStateResource,
-  createStateResource,
-  getEmbeddedResources,
-  StateResource,
-} from '@alfa-client/tech-shared';
+import { createStateResource, getEmbeddedResources, StateResource } from '@alfa-client/tech-shared';
 import { expectComponentExistsInTemplate, getElementFromFixtureByType } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { expect } from '@jest/globals';
@@ -33,6 +27,7 @@ describe('AggregationMappingListComponent', () => {
 
     fixture = TestBed.createComponent(AggregationMappingListComponent);
     component = fixture.componentInstance;
+    component.aggregationMappingListStateResource = createStateResource(createAggregationMappingListResource());
     fixture.detectChanges();
   });
 
@@ -40,55 +35,6 @@ describe('AggregationMappingListComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  describe('component', () => {
-    const aggregationMappingListStateResource: StateResource<AggregationMappingListResource> = createStateResource(
-      createAggregationMappingListResource(),
-    );
-
-    it('should have initial state', () => {
-      expect(component.listStateResource).toEqual(createEmptyStateResource());
-      expect(component.aggregationMappings).toEqual([]);
-    });
-
-    describe('update', () => {
-      it('should set list state resource', () => {
-        component.aggregationMappingListStateResource = aggregationMappingListStateResource;
-
-        expect(component.listStateResource).toEqual(aggregationMappingListStateResource);
-      });
-
-      it('should set aggregation mappings if loaded and not nil', () => {
-        component.aggregationMappingListStateResource = aggregationMappingListStateResource;
-
-        expect(component.aggregationMappings).toEqual(
-          getEmbeddedResources(aggregationMappingListStateResource, AggregationMappingListLinkRel.LIST),
-        );
-      });
-
-      it('should NOT set aggregation mappings if nil', () => {
-        component.aggregationMappingListStateResource = null;
-
-        expect(component.aggregationMappings).toEqual([]);
-      });
-
-      it('should NOT set aggregation mappings if loading', () => {
-        component.aggregationMappingListStateResource = createLoadingStateResource();
-
-        expect(component.aggregationMappings).toEqual([]);
-      });
-    });
-
-    describe('set aggregation mapping list state resource', () => {
-      it('should update component state', () => {
-        component._update = jest.fn();
-
-        component.aggregationMappingListStateResource = aggregationMappingListStateResource;
-
-        expect(component._update).toHaveBeenCalledWith(aggregationMappingListStateResource);
-      });
-    });
-  });
-
   describe('template', () => {
     const aggregationMappingListStateResource: StateResource<AggregationMappingListResource> = createStateResource(
       createAggregationMappingListResource(),
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.ts
index 4adecffe51..ac2c343c47 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.ts
@@ -1,5 +1,5 @@
-import { AggregationMappingListResource, AggregationMappingResource } from '@admin-client/reporting-shared';
-import { createEmptyStateResource, getEmbeddedResources, isLoaded, isNotNil, StateResource } from '@alfa-client/tech-shared';
+import { AggregationMappingListResource } from '@admin-client/reporting-shared';
+import { StateResource, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
 import { SpinnerComponent } from '@ods/component';
 import { ListComponent } from '@ods/system';
@@ -10,22 +10,10 @@ import { AggregationMappingListItemComponent } from './aggregation-mapping-list-
   selector: 'admin-aggregation-mapping-list',
   standalone: true,
   templateUrl: './aggregation-mapping-list.component.html',
-  imports: [SpinnerComponent, ListComponent, AggregationMappingListItemComponent],
+  imports: [SpinnerComponent, ListComponent, AggregationMappingListItemComponent, ToEmbeddedResourcesPipe],
 })
 export class AggregationMappingListComponent {
-  @Input({ required: true }) set aggregationMappingListStateResource(
-    stateResource: StateResource<AggregationMappingListResource>,
-  ) {
-    this._update(stateResource);
-  }
+  @Input({ required: true }) aggregationMappingListStateResource: StateResource<AggregationMappingListResource>;
 
-  public listStateResource: StateResource<AggregationMappingListResource> = createEmptyStateResource();
-  public aggregationMappings: AggregationMappingResource[] = [];
-
-  _update(stateResource: StateResource<AggregationMappingListResource>): void {
-    this.listStateResource = stateResource;
-    if (isNotNil(stateResource) && isLoaded(stateResource)) {
-      this.aggregationMappings = getEmbeddedResources(stateResource, AggregationMappingListLinkRel.LIST);
-    }
-  }
+  public readonly AggregationMappingListLinkRel = AggregationMappingListLinkRel;
 }
-- 
GitLab


From 8446229ddadf2e5ce5731f68649b8e1e65499aef Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 19:20:38 +0100
Subject: [PATCH 32/47] OZG-7473 rename const

Based on CR comment.
---
 .../src/lib/aggregation-mapping-resource.service.spec.ts  | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
index 4faae6e022..d9131bbba3 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.spec.ts
@@ -37,23 +37,23 @@ describe('AggregationMappingResourceService', () => {
   });
 
   describe('build config', () => {
-    const _getResourceByNavigationRoute: jest.SpyInstance = jest
+    const getResourceByNavigationRouteSpy: jest.SpyInstance = jest
       .spyOn(self, '_getResourceByNavigationRoute')
       .mockImplementation();
 
     afterAll(() => {
-      _getResourceByNavigationRoute.mockRestore();
+      getResourceByNavigationRouteSpy.mockRestore();
     });
 
     it('should get resource by navigation route', () => {
       self._buildResourceServiceConfig(useFromMock(repository), useFromMock(navigationService));
 
-      expect(_getResourceByNavigationRoute).toHaveBeenCalled();
+      expect(getResourceByNavigationRouteSpy).toHaveBeenCalled();
     });
 
     it('should have aggregation mapping static resource', () => {
       const staticResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
-      _getResourceByNavigationRoute.mockReturnValue(of(staticResource));
+      getResourceByNavigationRouteSpy.mockReturnValue(of(staticResource));
 
       const config: ResourceServiceConfig<AggregationMappingResource> = self._buildResourceServiceConfig(
         useFromMock(repository),
-- 
GitLab


From fa8af846e292545ce0972368739f04d2fdeb4ace Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 19:22:11 +0100
Subject: [PATCH 33/47] OZG-7473 rename method

Based on CR comment.
---
 .../aggregation-mapping.formservice.spec.ts                 | 4 ++--
 .../aggregation-mapping.formservice.ts                      | 2 +-
 .../src/lib/aggregation-mapping.service.spec.ts             | 6 +++---
 .../reporting-shared/src/lib/aggregation-mapping.service.ts | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
index 72ad99b1cc..8aae7f66f7 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.spec.ts
@@ -128,14 +128,14 @@ describe('AggregationMappingFormService', () => {
     const stateResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
 
     beforeEach(() => {
-      service.getByCurrentUrl.mockReturnValue(of(stateResource));
+      service.get.mockReturnValue(of(stateResource));
       formService._patchForm = jest.fn();
     });
 
     it('should get by current url', () => {
       formService.get();
 
-      expect(service.getByCurrentUrl).toHaveBeenCalled();
+      expect(service.get).toHaveBeenCalled();
     });
 
     it('should patch form', () => {
diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.ts
index 3096bf7854..09c620e51c 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping.formservice.ts
@@ -58,7 +58,7 @@ export class AggregationMappingFormservice extends AbstractFormService<Aggregati
   }
 
   public get(): Observable<StateResource<AggregationMappingResource>> {
-    return this.aggregationMappingService.getByCurrentUrl().pipe(
+    return this.aggregationMappingService.get().pipe(
       filter(isLoaded),
       tap((stateResource: StateResource<AggregationMappingResource>) => this._patchForm(stateResource.resource)),
     );
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
index 0846feed2d..a3fa52a58e 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
@@ -95,20 +95,20 @@ describe('AggregationMappingService', () => {
     });
   });
 
-  describe('get by current url', () => {
+  describe('get', () => {
     const stateResource = createStateResource(createAggregationMappingResource());
     beforeEach(() => {
       resourceService.get = jest.fn().mockReturnValue(of(stateResource));
     });
 
     it('should call resource service', () => {
-      service.getByCurrentUrl();
+      service.get();
 
       expect(resourceService.get).toHaveBeenCalled();
     });
 
     it('should emit resource', () => {
-      expect(service.getByCurrentUrl()).toBeObservable(singleColdCompleted(stateResource));
+      expect(service.get()).toBeObservable(singleColdCompleted(stateResource));
     });
   });
 
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
index 333d530998..96c72825e5 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
@@ -22,7 +22,7 @@ export class AggregationMappingService {
     this.listService.refresh();
   }
 
-  public getByCurrentUrl(): Observable<StateResource<AggregationMappingResource>> {
+  public get(): Observable<StateResource<AggregationMappingResource>> {
     return this.resourceService.get();
   }
 
-- 
GitLab


From beb977aa20ecdd96ea961635ab83ea4e1f42bc44 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 19:39:27 +0100
Subject: [PATCH 34/47] OZG-7473 revert change

Based on CR comment.
---
 alfa-client/libs/test-utils/src/lib/helper.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/test-utils/src/lib/helper.ts b/alfa-client/libs/test-utils/src/lib/helper.ts
index df9518764f..66f33c3579 100644
--- a/alfa-client/libs/test-utils/src/lib/helper.ts
+++ b/alfa-client/libs/test-utils/src/lib/helper.ts
@@ -26,8 +26,8 @@ import { ComponentFixture } from '@angular/core/testing';
 import { By } from '@angular/platform-browser';
 import { EventData } from './model';
 
-export function getElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): T | null {
-  return getDebugElementFromFixtureByType(fixture, component)?.componentInstance as T;
+export function getElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): T {
+  return getDebugElementFromFixtureByType(fixture, component).componentInstance as T;
 }
 
 function getDebugElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): DebugElement {
-- 
GitLab


From 70ada3873de91823f0671cedbe348fa2bddface7 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 19:40:06 +0100
Subject: [PATCH 35/47] OZG-7473 extract regex to const

Based on CR comment.
---
 .../tech-shared/src/lib/validation/tech.validation.util.ts     | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts
index 8ea81cca8d..638689f2ba 100644
--- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts
+++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts
@@ -111,5 +111,6 @@ export function getFieldPath(name: string, pathPrefix: string): string {
 }
 
 export function _mapFormArrayElementNameToPath(name: string): string {
-  return name.replace(/\[(\d+?)]\./g, '.$1.');
+  const formArrayControlIndexCaptureGroup: RegExp = /\[(\d+?)]\./g;
+  return name.replace(formArrayControlIndexCaptureGroup, '.$1.');
 }
-- 
GitLab


From 069d2d5b546056eb645e7cf880733e6fc90759e2 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Sun, 23 Mar 2025 20:48:21 +0100
Subject: [PATCH 36/47] OZG-7473 add test

Based on CR comment.
---
 .../resource/list-resource.service.spec.ts    | 24 +++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
index 648099dffa..def11057ce 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
@@ -28,13 +28,13 @@ import { Resource, ResourceUri } from '@ngxp/rest';
 import { cold } from 'jest-marbles';
 import { DummyLinkRel, DummyListLinkRel } from 'libs/tech-shared/test/dummy';
 import { createDummyListResource, createDummyResource, createFilledDummyListResource } from 'libs/tech-shared/test/resource';
-import { BehaviorSubject, Observable, of } from 'rxjs';
+import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
 import { multipleCold, singleCold, singleColdCompleted, singleHot } from '../../../test/marbles';
 import { ResourceListService } from './list-resource.service';
 import { CreateResourceData, LinkRelationName, ListItemResource, ListResourceServiceConfig } from './resource.model';
 import { ResourceRepository } from './resource.repository';
 import * as ResourceUtil from './resource.util';
-import { createEmptyStateResource, createErrorStateResource, createStateResource, ListResource, StateResource } from './resource.util';
+import { createEmptyStateResource, createErrorStateResource, createLoadingStateResource, createStateResource, ListResource, StateResource } from './resource.util';
 
 import { ProblemDetail } from '@alfa-client/tech-shared';
 import { expect } from '@jest/globals';
@@ -351,6 +351,26 @@ describe('ListResourceService', () => {
 
       expect(createdResource).toBeObservable(multipleCold(createEmptyStateResource(true), createStateResource(returnResource)));
     });
+
+    it('should handle error', () => {
+      const error: ProblemDetail = createProblemDetail();
+      service._handleError = jest.fn();
+      resourceRepository.createResource.mockReturnValue(throwError(() => error));
+
+      service.create(toCreate).subscribe();
+
+      expect(service._handleError).toHaveBeenCalledWith(error);
+    });
+
+    it('should emit on error', () => {
+      const error: ProblemDetail = createProblemDetail();
+      service._handleError = jest.fn().mockReturnValue(of(createErrorStateResource(error)));
+      resourceRepository.createResource.mockReturnValue(cold('-#', null, error));
+
+      expect(service.create(toCreate)).toBeObservable(
+        cold('a(b|)', { a: createLoadingStateResource(), b: createErrorStateResource(error) }),
+      );
+    });
   });
 
   describe('handle error', () => {
-- 
GitLab


From a4cb72a73a50551212edc62bfc5f79eadbe6ab0b Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Mon, 24 Mar 2025 11:30:52 +0100
Subject: [PATCH 37/47] OZG-7473 remove unnecessary binding

Based on CR comment.
---
 .../aggregation-mapping-field-list-form.component.html          | 2 --
 1 file changed, 2 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
index 958c7f9d5f..965537eeb0 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-form-container/aggregation-mapping-form/aggregation-mapping-field-list-form/aggregation-mapping-field-list-form.component.html
@@ -1,10 +1,8 @@
 <form [formGroup]="formService.form">
-  <div class="flex flex-col" [formArrayName]="AggregationMappingFormService.FIELD_MAPPINGS">
     <div *ngFor="let ignore of mappingsFormArray; let i = index">
       <admin-aggregation-mapping-field-form
         [index]="i"
         [attr.data-test-id]="'aggregation-mapping-field-mapping-form-' + i"
       ></admin-aggregation-mapping-field-form>
     </div>
-  </div>
 </form>
-- 
GitLab


From 71a443fc467e986c7ab6cc4b701cbb9af95a134b Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Mon, 24 Mar 2025 13:16:58 +0100
Subject: [PATCH 38/47] OZG-7591 move rxjs operator

---
 .../libs/tech-shared/src/lib/resource/list-resource.service.ts  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
index ae32eafd97..c98b96a0bf 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
@@ -102,8 +102,8 @@ export class ResourceListService<B extends Resource, T extends ListResource, I e
     this.verifyBeforeCreation();
     return this.repository.createResource(this.buildCreateResourceData(toCreate, this.config.createLinkRel)).pipe(
       map((listItemResource: I) => createStateResource(listItemResource)),
-      startWith(createEmptyStateResource<I>(true)),
       catchError((error: ProblemDetail) => this._handleError(error)),
+      startWith(createEmptyStateResource<I>(true)),
     );
   }
 
-- 
GitLab


From 3580a0f406afa2c8e811356e997805d2478058c8 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Mon, 24 Mar 2025 13:19:34 +0100
Subject: [PATCH 39/47] OZG-7591 rename route

---
 .../admin-e2e/src/page-objects/main.po.ts     |  2 +-
 .../apps/admin/src/app/app.component.spec.ts  | 19 ++++++++++++++++---
 .../libs/admin/shared/src/lib/routes.ts       |  2 +-
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
index e2b33614a9..b07542fc24 100644
--- a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
+++ b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
@@ -31,7 +31,7 @@ export class MainPage {
   private readonly benutzerNavigationItem: string = 'link-path-benutzer';
   private readonly organisationEinheitNavigationItem: string = 'link-path-organisationseinheiten';
   private readonly postfachNavigationItem: string = 'link-path-postfach';
-  private readonly statistikNavigationItem: string = 'link-path-auswertung';
+  private readonly statistikNavigationItem: string = 'link-path-auswertungen';
 
   public getBuildInfo(): BuildInfoE2EComponent {
     return this.buildInfo;
diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts
index 3c1142c2c7..fb01cab1df 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -27,11 +27,24 @@ import { KeycloakTokenService } from '@admin/keycloak-shared';
 import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
 import { BuildInfoComponent } from '@alfa-client/common';
 import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, getElementComponentFromFixtureByCss, Mock, mock, notExistsAsHtmlElement, } from '@alfa-client/test-utils';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  Mock,
+  mock,
+  notExistsAsHtmlElement,
+} from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
 import { AuthenticationService } from '@authentication';
-import { AdminLogoIconComponent, MailboxIconComponent, NavbarComponent, NavItemComponent, OrgaUnitIconComponent, UsersIconComponent, } from '@ods/system';
+import {
+  AdminLogoIconComponent,
+  MailboxIconComponent,
+  NavbarComponent,
+  NavItemComponent,
+  OrgaUnitIconComponent,
+  UsersIconComponent,
+} from '@ods/system';
 import { createConfigurationResource } from 'libs/admin/configuration-shared/test/configuration';
 import { MenuContainerComponent } from 'libs/admin/configuration/src/lib/menu-container/menu-container.component';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
@@ -297,7 +310,7 @@ describe('AppComponent', () => {
       it('should navigate to statistik if aggregation mapping link exists', () => {
         component._navigateByConfiguration(createConfigurationResource([ConfigurationLinkRel.AGGREGATION_MAPPINGS]));
 
-        expect(router.navigate).toHaveBeenCalledWith(['/auswertung']);
+        expect(router.navigate).toHaveBeenCalledWith(['/auswertungen']);
       });
 
       it('should navigate to unavailable page if no link exists', () => {
diff --git a/alfa-client/libs/admin/shared/src/lib/routes.ts b/alfa-client/libs/admin/shared/src/lib/routes.ts
index 6802911d70..d5b4ed6de1 100644
--- a/alfa-client/libs/admin/shared/src/lib/routes.ts
+++ b/alfa-client/libs/admin/shared/src/lib/routes.ts
@@ -28,7 +28,7 @@ export enum ROUTES {
   BENUTZER_ID = 'benutzer/:userid',
   ORGANISATIONSEINHEITEN = 'organisationseinheiten',
   UNAVAILABLE = 'unavailable',
-  AGGREGATION_MAPPING = 'auswertung',
+  AGGREGATION_MAPPING = 'auswertungen',
   AGGREGATION_MAPPING_NEU = 'auswertung/neu',
   AGGREGATION_MAPPING_ID = 'auswertung/:aggregationMappingId',
 }
-- 
GitLab


From 05d2dcce767e7110b6ee933b6edbd32e21c2e119 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Mon, 24 Mar 2025 15:52:37 +0100
Subject: [PATCH 40/47] OZG-7473 rename routes

Based on CR comment.
---
 alfa-client/libs/admin/shared/src/lib/routes.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/admin/shared/src/lib/routes.ts b/alfa-client/libs/admin/shared/src/lib/routes.ts
index d5b4ed6de1..9f1496843e 100644
--- a/alfa-client/libs/admin/shared/src/lib/routes.ts
+++ b/alfa-client/libs/admin/shared/src/lib/routes.ts
@@ -29,6 +29,6 @@ export enum ROUTES {
   ORGANISATIONSEINHEITEN = 'organisationseinheiten',
   UNAVAILABLE = 'unavailable',
   AGGREGATION_MAPPING = 'auswertungen',
-  AGGREGATION_MAPPING_NEU = 'auswertung/neu',
-  AGGREGATION_MAPPING_ID = 'auswertung/:aggregationMappingId',
+  AGGREGATION_MAPPING_NEU = 'auswertungen/neu',
+  AGGREGATION_MAPPING_ID = 'auswertungen/:aggregationMappingId',
 }
-- 
GitLab


From 2672bb13bdcf52e34e6df598231b0f95c872205a Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 25 Mar 2025 11:01:56 +0100
Subject: [PATCH 41/47] OZG-7473 add index.ts entry

Based on CR comment.
---
 .../aggregation-mapping-list.component.spec.ts                 | 3 +--
 alfa-client/libs/admin/reporting-shared/src/index.ts           | 1 +
 .../libs/admin/reporting-shared/test/aggregation-mapping.ts    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
index 1a6e2d40a4..4dbf9393d2 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
@@ -1,4 +1,4 @@
-import { AggregationMappingListResource } from '@admin-client/reporting-shared';
+import { AggregationMappingListLinkRel, AggregationMappingListResource } from '@admin-client/reporting-shared';
 import { createStateResource, getEmbeddedResources, StateResource } from '@alfa-client/tech-shared';
 import { expectComponentExistsInTemplate, getElementFromFixtureByType } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
@@ -6,7 +6,6 @@ import { expect } from '@jest/globals';
 import { SpinnerComponent } from '@ods/component';
 import { ListComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
-import { AggregationMappingListLinkRel } from '../../../../../reporting-shared/src/lib/aggregation-mapping.linkrel';
 import { createAggregationMappingListResource } from '../../../../../reporting-shared/test/aggregation-mapping';
 import { AggregationMappingListItemComponent } from './aggregation-mapping-list-item/aggregation-mapping-list-item.component';
 import { AggregationMappingListComponent } from './aggregation-mapping-list.component';
diff --git a/alfa-client/libs/admin/reporting-shared/src/index.ts b/alfa-client/libs/admin/reporting-shared/src/index.ts
index 42e6a9bbe0..17fd61a17a 100644
--- a/alfa-client/libs/admin/reporting-shared/src/index.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/index.ts
@@ -1,5 +1,6 @@
 export * from './lib/aggregation-mapping-list-resource.service';
 export * from './lib/aggregation-mapping-resource.service';
+export * from './lib/aggregation-mapping.linkrel';
 export * from './lib/aggregation-mapping.model';
 export * from './lib/aggregation-mapping.provider';
 export * from './lib/aggregation-mapping.service';
diff --git a/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts b/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
index e71b646a80..3506ea96a8 100644
--- a/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
+++ b/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
@@ -1,9 +1,9 @@
+import { AggregationMappingListLinkRel } from '@admin-client/reporting-shared';
 import { faker } from '@faker-js/faker';
 import { times } from 'lodash-es';
 import { LinkRelationName } from '../../../tech-shared/src';
 import { toResource } from '../../../tech-shared/test/resource';
 import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from '../src';
-import { AggregationMappingListLinkRel } from '../src/lib/aggregation-mapping.linkrel';
 
 export function createAggregationMapping(): AggregationMapping {
   return {
-- 
GitLab


From 86e5f6a8a365796c8de8624f3c82f13b6354af81 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 25 Mar 2025 11:02:31 +0100
Subject: [PATCH 42/47] OZG-7473 add type

Based on CR comment.
---
 .../aggregation-mapping-list-container.component.spec.ts        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts
index f9fe5b7e4a..7548de0fe9 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list-container.component.spec.ts
@@ -109,7 +109,7 @@ describe('AggregationMappingListContainerComponent', () => {
         component.listStateResource$ = of(stateResource);
         fixture.detectChanges();
 
-        const comp = getElementFromFixtureByType(fixture, AggregationMappingListComponent);
+        const comp: AggregationMappingListComponent = getElementFromFixtureByType(fixture, AggregationMappingListComponent);
 
         expect(comp.aggregationMappingListStateResource).toEqual(stateResource);
       });
-- 
GitLab


From bb10b0d1a9fb47bbf25e78628c9d33801a35b229 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 25 Mar 2025 11:03:17 +0100
Subject: [PATCH 43/47] OZG-7473 add types

Based on CR comment.
---
 .../src/lib/aggregation-mapping.service.spec.ts               | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
index a3fa52a58e..73194b1e4c 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
@@ -96,7 +96,7 @@ describe('AggregationMappingService', () => {
   });
 
   describe('get', () => {
-    const stateResource = createStateResource(createAggregationMappingResource());
+    const stateResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
     beforeEach(() => {
       resourceService.get = jest.fn().mockReturnValue(of(stateResource));
     });
@@ -114,7 +114,7 @@ describe('AggregationMappingService', () => {
 
   describe('save', () => {
     const aggregationMapping: AggregationMapping = createAggregationMapping();
-    const stateResource = createStateResource(createAggregationMappingResource());
+    const stateResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
     beforeEach(() => {
       resourceService.save = jest.fn().mockReturnValue(of(stateResource));
     });
-- 
GitLab


From d06549569802006f6227f41efe8d43a1dadf39a9 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 25 Mar 2025 11:06:27 +0100
Subject: [PATCH 44/47] OZG-7473 given when then

Based on CR comment.
---
 .../src/lib/aggregation-mapping.service.spec.ts           | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
index 73194b1e4c..4e21e50174 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
@@ -108,7 +108,9 @@ describe('AggregationMappingService', () => {
     });
 
     it('should emit resource', () => {
-      expect(service.get()).toBeObservable(singleColdCompleted(stateResource));
+      const got$: Observable<StateResource<AggregationMappingResource>> = service.get();
+
+      expect(got$).toBeObservable(singleColdCompleted(stateResource));
     });
   });
 
@@ -126,7 +128,9 @@ describe('AggregationMappingService', () => {
     });
 
     it('should emit saved state resource', () => {
-      expect(service.save(aggregationMapping)).toBeObservable(singleColdCompleted(stateResource));
+      const saved$: Observable<StateResource<AggregationMappingResource>> = service.save(aggregationMapping);
+
+      expect(saved$).toBeObservable(singleColdCompleted(stateResource));
     });
   });
 });
-- 
GitLab


From 12bcc54bf9cc3108d8497990f8f11f3f8005a6a8 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 25 Mar 2025 11:09:52 +0100
Subject: [PATCH 45/47] OZG-7473 format import

Based on CR comment.
---
 .../src/lib/validation/tech.validation.util.spec.ts   | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts
index f5a6a56fb0..b4a1c44268 100644
--- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts
@@ -26,7 +26,16 @@ import { faker } from '@faker-js/faker';
 import { createInvalidParam, createIssue, createProblemDetail } from '../../../test/error';
 import { InvalidParam, Issue } from '../tech.model';
 import { VALIDATION_MESSAGES, ValidationMessageCode } from './tech.validation.messages';
-import { getControlForInvalidParam, getControlForIssue, getFieldPath, getMessageForInvalidParam, getMessageForIssue, getMessageReason, setInvalidParamValidationError, setIssueValidationError, } from './tech.validation.util';
+import {
+  getControlForInvalidParam,
+  getControlForIssue,
+  getFieldPath,
+  getMessageForInvalidParam,
+  getMessageForIssue,
+  getMessageReason,
+  setInvalidParamValidationError,
+  setIssueValidationError,
+} from './tech.validation.util';
 
 describe('ValidationUtils', () => {
   const baseField1Control: FormControl = new UntypedFormControl();
-- 
GitLab


From a57b75b8380943cea29e8315056a98eb1051e055 Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 25 Mar 2025 11:16:49 +0100
Subject: [PATCH 46/47] OZG-7473 remove function

Based on CR comment.
---
 alfa-client/libs/test-utils/src/lib/jest.helper.ts | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/alfa-client/libs/test-utils/src/lib/jest.helper.ts b/alfa-client/libs/test-utils/src/lib/jest.helper.ts
index 1b0f86ec5b..4d0c827161 100644
--- a/alfa-client/libs/test-utils/src/lib/jest.helper.ts
+++ b/alfa-client/libs/test-utils/src/lib/jest.helper.ts
@@ -39,10 +39,6 @@ export function expectComponentExistsInTemplate<T>(fixture: ComponentFixture<any
   expect(getElementFromFixtureByType(fixture, component)).toBeInstanceOf(component);
 }
 
-export function expectComponentMissingInTemplate<T>(fixture: ComponentFixture<any>, component: Type<T>): void {
-  expect(getElementFromFixtureByType(fixture, component)).toBeUndefined();
-}
-
 export function tooltipExistsWithText(fixture: ComponentFixture<any>, domElement: string, tooltipText: string) {
   const tooltipInstance = getDebugElementFromFixtureByCss(fixture, domElement).injector.get(TooltipDirective);
   expect(tooltipInstance.componentRef.instance.text).toBe(tooltipText);
-- 
GitLab


From 81af1208ef43145b025c29af5eff17c380b0849d Mon Sep 17 00:00:00 2001
From: sebo <sebastian.bergandy@external.mgm-cp.com>
Date: Tue, 25 Mar 2025 12:10:11 +0100
Subject: [PATCH 47/47] OZG-7473 improve code

Based on CR comment.
---
 .../aggregation-mapping-list.component.spec.ts               | 5 +++--
 .../src/lib/aggregation-mapping.service.spec.ts              | 5 +++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
index 4dbf9393d2..37718ad397 100644
--- a/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
+++ b/alfa-client/libs/admin/aggregation-mapping/src/lib/aggregation-mapping-list-container/aggregation-mapping-list/aggregation-mapping-list.component.spec.ts
@@ -49,12 +49,13 @@ describe('AggregationMappingListComponent', () => {
     });
 
     it('should have spinner with state resource', () => {
-      const comp = getElementFromFixtureByType(fixture, SpinnerComponent);
+      const comp: SpinnerComponent = getElementFromFixtureByType(fixture, SpinnerComponent);
+
       expect(comp.stateResource).toEqual(aggregationMappingListStateResource);
     });
 
     it('should have list item with mapping', () => {
-      const comp = getElementFromFixtureByType(fixture, AggregationMappingListItemComponent);
+      const comp: AggregationMappingListItemComponent = getElementFromFixtureByType(fixture, AggregationMappingListItemComponent);
       expect(comp.aggregationMapping).toEqual(
         getEmbeddedResources(aggregationMappingListStateResource, AggregationMappingListLinkRel.LIST)[0],
       );
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
index 4e21e50174..bca88ee563 100644
--- a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
@@ -97,6 +97,7 @@ describe('AggregationMappingService', () => {
 
   describe('get', () => {
     const stateResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
+
     beforeEach(() => {
       resourceService.get = jest.fn().mockReturnValue(of(stateResource));
     });
@@ -108,9 +109,9 @@ describe('AggregationMappingService', () => {
     });
 
     it('should emit resource', () => {
-      const got$: Observable<StateResource<AggregationMappingResource>> = service.get();
+      const stateResource$: Observable<StateResource<AggregationMappingResource>> = service.get();
 
-      expect(got$).toBeObservable(singleColdCompleted(stateResource));
+      expect(stateResource$).toBeObservable(singleColdCompleted(stateResource));
     });
   });
 
-- 
GitLab