Merge branch 'SI-753-Mehrere-Stationen-einer-Meldung-zuweisen' of ssh://git.eclipse.org:29418/openk-usermodules/org.eclipse.openk-usermodules.gridFailureInformation.frontend into DEVELOP
diff --git a/i18n/general.de.json b/i18n/general.de.json
index 5acad0d..2977d28 100644
--- a/i18n/general.de.json
+++ b/i18n/general.de.json
@@ -16,6 +16,7 @@
   "CloseBtn": "Schließen",
   "BackBtn": "Zurück",
   "QualifyBtn": "Qualifizieren",
+  "PublishBtn": "Veröffentlichen",
   "StornoBtn": "Stornieren",
   "CreatedBtn": "Anlegen",
   "GridEmptyLabel": "Keine Daten vorhanden!",
@@ -29,6 +30,7 @@
   "MandatoryMapFieldError": "Es muss ein Ort festgelegt werden.",
   "SelectOption": "Bitte auswählen",
   "Search": "Suchen",
+  "PublicationRequiresAtLeastOneChannel": "Zur Veröffentlichung der Störungsmeldung muss mindestens ein Veröffentlichungskanal ausgewählt sein.",
 
   "ConfirmDialog": {
     "Title": "Bitte bestätigen Sie",
diff --git a/i18n/grid-failure.de.json b/i18n/grid-failure.de.json
index dbc6065..c67fc28 100644
--- a/i18n/grid-failure.de.json
+++ b/i18n/grid-failure.de.json
@@ -50,5 +50,9 @@
     "Map": "Karte",
     "Description": "Beschreibung",
     "AssignGroupBtn": "Verteilergruppe zuordnen",
-   "AddStation": "Station hinzufügen"  }
+    "PublicationChannels": "Veröffentlichungskanäle",
+    "DistributionGroups": "Verteilergruppen",
+    "ChannelSaveBtn": "Kanäle speichern",
+	"AddStation": "Station hinzufügen"
+  }
 }
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts
index 1557da6..cf8a52d 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts
@@ -25,6 +25,7 @@
   FailureHousenumber,
   FailureAddress,
   DistributionGroup,
+  PublicationChannel,
   Polygon,
 } from '@grid-failure-information-app/shared/models';
 
@@ -48,7 +49,7 @@
 
   @PUT('/grid-failure-informations/{id}')
   @Adapter(GridFailureService.itemAdapter)
-  public putGridFailure(@Path('id') id: string, @Body() gridFailure: GridFailure): Observable<GridFailure> {
+  public putGridFailure(@Path('id') id: string, @Body() gridFailure: GridFailure, @Query('saveForPublish') saveForPublish: boolean): Observable<GridFailure> {
     return null;
   }
 
@@ -219,4 +220,22 @@
   public deleteDistributionGroupAssignment(@Path('gridFailureId') gridFailureId: string, @Path('groupId') groupId: string): Observable<DistributionGroup> {
     return null;
   }
+
+  @POST('/grid-failure-informations/{gridFailureId}/channels')
+  @Adapter(GridFailureService.publicationChannelAdapter)
+  public postPublicationChannelAssignment(
+    @Path('gridFailureId') gridFailureId: string,
+    @Query('publicationChannel') publicationChannel: string
+  ): Observable<PublicationChannel> {
+    return null;
+  }
+
+  @DELETE('/grid-failure-informations/{gridFailureId}/channels')
+  @Adapter(GridFailureService.publicationChannelAdapter)
+  public deletePublicationChannelAssignment(
+    @Path('gridFailureId') gridFailureId: string,
+    @Query('publicationChannel') publicationChannel: string
+  ): Observable<PublicationChannel> {
+    return null;
+  }
 }
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html
index 4944ae9..a8b513e 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html
@@ -31,6 +31,18 @@
           </ng-container>
         </div>
         <div *ngIf="gridFailureDetailsSandbox.currentFormState?.isEnabled">
+          <ng-container *ngIf="gridFailureDetailsSandbox.showPublishButton && gridFailureDetailsSandbox.currentFormState.isEnabled">
+            <button
+              *visibleByRight="RolesEnum.PUBLISHER"
+              [disabled]="gridFailureDetailsSandbox.disablePublishButton"
+              [ngClass]="{ disabledButton: gridFailureDetailsSandbox.disablePublishButton }"
+              type="button"
+              class="btn btn-primary button"
+              (click)="gridFailureDetailsSandbox.setPublishedState()"
+            >
+              {{ 'PublishBtn' | translate }}
+            </button>
+          </ng-container>
           <ng-container *ngIf="gridFailureDetailsSandbox.showQualifyButton">
             <button
               *visibleByRight="RolesEnum.QUALIFIER"
@@ -161,10 +173,15 @@
             <div class="form-group row">
               <label for="publicationStatus" class="col-sm-2 col-form-label">{{ 'GridFailure.PublicationStatus' | translate }}</label>
               <div class="col-sm-4">
-                <select type="text" class="form-control" id="publicationStatus" [ngrxFormControlState]="formState.controls['publicationStatus']">
-                  <option [value]="null" selected>{{ 'SelectOption' | translate }}</option>
-                  <option *ngFor="let enum of gridFailureDetailsSandbox.publicationStatusEnum | keyvalue" [value]="enum.key">{{ enum.value }}</option>
-                </select>
+                <input
+                  id="publicationStatus"
+                  type="text"
+                  maxlength="255"
+                  class="form-control"
+                  [ngrxFormControlState]="formState.controls['publicationStatus']"
+                  autocomplete="off"
+                  readonly
+                />
               </div>
             </div>
           </div>
@@ -438,7 +455,12 @@
                 <div class="form-group row">
                   <label for="radius" class="col-sm-5 col-form-label">{{ 'GridFailure.RadiusInMeter' | translate }}</label>
                   <div class="col-sm-6">
-                    <select required type="text" class="form-control" [ngrxFormControlState]="formState.controls['radiusId']">
+                    <select
+                      [required]="gridFailureDetailsSandbox.isFieldRequiredDependingOnBranchId"
+                      type="text"
+                      class="form-control"
+                      [ngrxFormControlState]="formState.controls['radiusId']"
+                    >
                       <option [value]="null" selected disabled>{{ 'SelectOption' | translate }}</option>
                       <option *ngFor="let item of gridFailureDetailsSandbox.gridFailureRadii$ | async" [value]="item.id">{{ item.radius }}</option>
                     </select>
@@ -452,6 +474,7 @@
                   <div class="col-sm-6">
                     <input
                       [required]="gridFailureDetailsSandbox.isFieldRequiredDependingOnBranchId"
+                      [disabled]="gridFailureDetailsSandbox.disableStationAttributes"
                       #searchInput
                       placeholder="{{ 'GridFailure.StationDescription' | translate }}"
                       type="text"
@@ -466,7 +489,12 @@
                       [inputFormatter]="gridFailureDetailsSandbox.formatter"
                     />
                   </div>
-                  <button type="button" class="btn btn-primary btn-sm" (click)="gridFailureDetailsSandbox.postSelectedStation(); clearSearchInput()">
+                  <button
+                    type="button"
+                    class="btn btn-primary btn-sm"
+                    (click)="gridFailureDetailsSandbox.postSelectedStation(); clearSearchInput()"
+                    [disabled]="gridFailureDetailsSandbox.disableStationAttributes"
+                  >
                     {{ 'GridFailure.AddStation' | translate }}
                   </button>
                 </div>
@@ -496,11 +524,29 @@
           </div>
         </app-expandable>
 
-        <!-- distribution-groups -->
+        <!-- publication: publication-channels and distribution-groups -->
         <div *ngIf="gridFailureDetailsSandbox.checkForMaxVersion()">
           <app-expandable [showBodyInitially]="true" *visibleByRight="[RolesEnum.PUBLISHER]">
             <label header>{{ 'GridFailure.AssignedDistributionsGroup' | translate }}</label>
             <div class="expandable-content" body>
+              <div class="d-flex justify-content-between">
+                <h6>{{ 'GridFailure.PublicationChannels' | translate }}</h6>
+              </div>
+              <div *ngFor="let channel of gridFailureDetailsSandbox.exportChannels$ | async; let i = index">
+                <div class="custom-control custom-switch channel-input">
+                  <input
+                    type="checkbox"
+                    class="custom-control-input"
+                    id="{{ 'channel' + i }}"
+                    [checked]="
+                      gridFailureDetailsSandbox.currentFormState.value.publicationChannels['value'] &&
+                      gridFailureDetailsSandbox.currentFormState.value.publicationChannels['value'].includes(channel)
+                    "
+                    (change)="gridFailureDetailsSandbox.setPublicationChannels(channel, $event.target.checked)"
+                  />
+                  <label class="custom-control-label" for="{{ 'channel' + i }}">{{ channel }} </label>
+                </div>
+              </div>
               <app-grid-failure-distribution-groups></app-grid-failure-distribution-groups>
             </div>
           </app-expandable>
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.scss b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.scss
index 0b4bb4e..b0cb7b5 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.scss
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.scss
@@ -110,6 +110,13 @@
 .form-group:last-child {
   margin-bottom: 10px;
 }
+.channel-input {
+  margin-left: 12px;
+}
+.disabledButton {
+  background-color: #337ab7;
+  cursor: default;
+}
 .row {
   display: flex;
   flex-direction: row;
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
index ba73297..09dac39 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
@@ -103,14 +103,14 @@
 
   it('should dispatch loadGridFailureVersion Action via loadGridFailureVersion(VsNo)', () => {
     service['gridFailureId'] = 'id';
-    service.loadGridFailureVersion(1);
+    service.loadGridFailureVersion('1');
     expect(appState.dispatch).toHaveBeenCalledTimes(3);
   });
 
   it('should dispatch loadGridFailureVersion Action via loadGridFailureVersion(VsNo)', () => {
     service['gridFailureId'] = 'id';
     service.maxVersionNumber = 2;
-    service.loadGridFailureVersion(1);
+    service.loadGridFailureVersion('1');
     expect(appState.dispatch).toHaveBeenCalledTimes(3);
   });
 
@@ -147,7 +147,9 @@
     (service.currentFormState as any).userDefinedProperties = { controlId: '' };
 
     service.saveGridFailure();
-    expect(dispatchSpy).toHaveBeenCalledWith(Object({ payload: gfdetail, type: gridFailureActions.saveGridFailure.type }));
+    expect(dispatchSpy).toHaveBeenCalledWith(
+      Object({ payload: { gridFailure: gfdetail, saveForPublish: false }, type: gridFailureActions.saveGridFailure.type })
+    );
     expect(spy1).toHaveBeenCalled();
   });
 
@@ -348,6 +350,7 @@
     expect(spySave).toHaveBeenCalled();
     expect(dispatchSpy).toHaveBeenCalled();
   });
+
   it('should set the state in form to qualify and call save fuction', () => {
     service.gridFailureStates$ = { pipe: () => of({}), map: () => of({}) } as any;
     spyOn(service.gridFailureStates$, 'pipe').and.returnValue(of([{ status: StateEnum.QUALIFIED, id: '123' }]));
@@ -683,4 +686,56 @@
       gridFailureActions.createDistributionGroupAssignment({ gridFailureId: 'x1', newGroup: selectedDistributionGroup })
     );
   });
+
+  it('should displayNotification when publishing is attempted without at least one selected channel', () => {
+    const spy: any = spyOn(service['_utilService'], 'displayNotification');
+    const gfdetail = new GridFailure();
+    gfdetail.id = 'id';
+    gfdetail.publicationChannels = new Array();
+    gfdetail.publicationChannels['value'] = [];
+    service.currentFormState = INITIAL_STATE;
+    (service.currentFormState as any).isValid = true;
+    (service.currentFormState as any).value = gfdetail;
+    service.setPublishedState();
+    expect(spy).toHaveBeenCalled;
+  });
+
+  it('should call saveGridFailure() when publishing with at least one selected channel', () => {
+    const spy: any = spyOn(service, 'saveGridFailure');
+    const gfdetail = new GridFailure();
+    gfdetail.id = 'id';
+    gfdetail.publicationChannels = new Array();
+    gfdetail.publicationChannels['value'] = ['SMS'];
+    service.currentFormState = INITIAL_STATE;
+    (service.currentFormState as any).isValid = true;
+    (service.currentFormState as any).value = gfdetail;
+    service.setPublishedState();
+    expect(spy).toHaveBeenCalled;
+  });
+
+  it('should dispatch createPublicationChannelAssignment action if a channel was checked', () => {
+    const gfdetail = new GridFailure();
+    gfdetail.id = 'id';
+    gfdetail.publicationChannels = new Array();
+    gfdetail.publicationChannels['value'] = ['SMS'];
+    service.currentFormState = INITIAL_STATE;
+    (service.currentFormState as any).isValid = true;
+    (service.currentFormState as any).value = gfdetail;
+    service['_gridFailureId'] = 'x1';
+    service.setPublicationChannels('SMS', true);
+    expect(appState.dispatch).toHaveBeenCalledWith(gridFailureActions.createPublicationChannelAssignment({ gridFailureId: 'x1', channel: 'SMS' }));
+  });
+
+  it('should dispatch deletePublicationChannelAssignment action if a channel was unchecked', () => {
+    const gfdetail = new GridFailure();
+    gfdetail.id = 'id';
+    gfdetail.publicationChannels = new Array();
+    gfdetail.publicationChannels['value'] = ['SMS'];
+    service.currentFormState = INITIAL_STATE;
+    (service.currentFormState as any).isValid = true;
+    (service.currentFormState as any).value = gfdetail;
+    service['_gridFailureId'] = 'x1';
+    service.setPublicationChannels('SMS', false);
+    expect(appState.dispatch).toHaveBeenCalledWith(gridFailureActions.deletePublicationChannelAssignment({ gridFailureId: 'x1', channel: 'SMS' }));
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
index fd7ab30..23b8eed 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
@@ -46,6 +46,7 @@
   box,
   MarkAsTouchedAction,
   MarkAsDirtyAction,
+  unbox,
 } from 'ngrx-forms';
 import { combineLatest, Observable } from 'rxjs';
 import { debounceTime, distinctUntilChanged, map, skipWhile, take, takeUntil, tap } from 'rxjs/operators';
@@ -55,6 +56,7 @@
 export class GridFailureDetailsSandbox extends BaseFormSandbox<models.GridFailure> {
   public Globals = Globals;
   public StateEnum = enums.StateEnum;
+  public PublicationStatusEnum = enums.PublicationStatusEnum;
   public gridFailureDetailsFormState$: Observable<FormGroupState<models.GridFailure>> = this.appState$.select(store.getGridFailuresDetails);
   public currentFormState: FormGroupState<models.GridFailure>;
   public gridFailureClassifications$: Observable<models.FailureClassification[]> = this.appState$.select(store.getGridFailureClassificationsData);
@@ -111,12 +113,16 @@
   public showStornoButton: boolean = false;
   public showCreatedButton: boolean = false;
   public showUpdateButton: boolean = false;
+  public showPublishButton: boolean = false;
   public gridFailureAddress: models.FailureAddress;
   private _stations: Array<models.FailureStation> = new Array<models.FailureStation>();
 
   public gridFailureDistributionGroups$: Observable<models.DistributionGroup[]> = this.appState$.select(store.getGridFailureDistributionGroupsData);
   public gridFailureDistributionGroupsLoading$: Observable<boolean> = this.appState$.select(store.getGridFailureDistributionGroupsLoading);
   public distributionGroups$: Observable<models.DistributionGroup[]> = this.appState$.select(store.getDistributionGroupsData);
+  public exportChannels$: Observable<string[]> = this.appState$.select(store.getExportChannels);
+  public disablePublishButton: boolean;
+  public disableStationAttributes = false;
 
   private _gridFailureStations: Array<models.FailureStation> = new Array<models.FailureStation>();
   private _gridFailureId: string;
@@ -197,14 +203,20 @@
     this.appState$.dispatch(gridFailureActions.loadGridFailureVersions({ payload: gridFailureId }));
   }
 
-  public loadGridFailureVersion(versionNumber: number): void {
-    this.appState$.dispatch(gridFailureActions.loadGridFailureVersion({ gridFailureId: this._gridFailureId, versionNumber: versionNumber }));
-
+  public loadGridFailureVersion(versionNumber: string): void {
+    if (!!versionNumber && +versionNumber === this.maxVersionNumber) {
+      //necessary because of not-versioned publication properties
+      this.appState$.dispatch(gridFailureActions.loadGridFailureDetail({ payload: this._gridFailureId }));
+    } else {
+      this.appState$.dispatch(gridFailureActions.loadGridFailureVersion({ gridFailureId: this._gridFailureId, versionNumber: +versionNumber }));
+    }
     this.loadGridFailureBranches();
-    if (versionNumber < this.maxVersionNumber) {
+    if (+versionNumber < this.maxVersionNumber) {
       this.appState$.dispatch(new DisableAction(FORM_ID));
+      this.disableStationAttributes = true;
     } else {
       this.appState$.dispatch(new EnableAction(FORM_ID));
+      this.disableStationAttributes = false;
     }
   }
   public setGridFailureId(gridFailureId: string) {
@@ -233,6 +245,14 @@
       });
   }
 
+  public setPublishedState(): void {
+    if (this.currentFormState.value.publicationChannels['value'].length === 0) {
+      this._utilService.displayNotification('PublicationRequiresAtLeastOneChannel', 'alert');
+    } else {
+      this.saveGridFailure(true);
+    }
+  }
+
   public cancel(): void {
     if (!this.currentFormState.isPristine) {
       const modalRef = this._modalService.open(SafetyQueryDialogComponent);
@@ -249,7 +269,7 @@
     }
   }
 
-  public saveGridFailure(): void {
+  public saveGridFailure(saveForPublish: boolean = false): void {
     if (this.currentFormState.isValid) {
       if (this._assignedDistributionGroups && this._assignedDistributionGroups.length > 0) {
         let distributionGroupUuids: string[] = [];
@@ -262,7 +282,7 @@
 
       this.appState$.dispatch(
         gridFailureActions.saveGridFailure({
-          payload: unboxProperties<models.GridFailure>(this.currentFormState.value),
+          payload: { gridFailure: unboxProperties<models.GridFailure>(this.currentFormState.value), saveForPublish: saveForPublish },
         })
       );
       this.actionsSubject.pipe(ofType(gridFailureActions.saveGridFailureSuccess), take(1), takeUntil(this._endSubscriptions$)).subscribe(() => {
@@ -385,6 +405,7 @@
         ofType(gridFailureActions.loadGridFailureVersionsSuccess),
         takeUntil(this._endSubscriptions$),
         map(action => {
+          this.disablePublishButton = this.currentFormState.value.publicationStatus === enums.PublicationStatusEnum.VE;
           const gridFailures: models.GridFailure[] = action['payload'];
           return !!gridFailures && Math.max(...gridFailures.map(o => o.versionNumber));
         })
@@ -533,7 +554,7 @@
         ...this.currentFormState.value,
         stationDescription: null,
         stationId: null,
-        stationIds: [],
+        stationIds: box([]),
         addressPolygonPoints: null,
         latitude: null,
         longitude: null,
@@ -554,6 +575,7 @@
       case Globals.FAILURE_LOCATION_NS:
         this.appState$.dispatch(new EnableAction(INITIAL_STATE.controls.postcode.id));
         this.appState$.dispatch(new EnableAction(INITIAL_STATE.controls.radiusId.id));
+        this._disableStationControls();
 
         break;
       case Globals.FAILURE_LOCATION_MS:
@@ -561,12 +583,39 @@
         break;
       case Globals.FAILURE_LOCATION_MAP:
         this._disableAddressControls();
+        this._disableStationControls();
         break;
       default:
         break;
     }
   }
 
+  public setPublicationChannels(channel: string, checked: boolean) {
+    let publicationChannels = this.currentFormState.value.publicationChannels['value'];
+    if (checked) {
+      this.appState$.dispatch(gridFailureActions.createPublicationChannelAssignment({ gridFailureId: this._gridFailureId, channel: channel }));
+      this.actionsSubject
+        .pipe(
+          ofType(gridFailureActions.createPublicationChannelAssignmentSuccess),
+          map(action => action.payload),
+          takeUntil(this._endSubscriptions$)
+        )
+        .subscribe((publicationChannel: models.PublicationChannel) => {
+          publicationChannels.push(publicationChannel.publicationChannel);
+          if (this.disablePublishButton && !publicationChannel.published) {
+            this.disablePublishButton = false;
+          }
+          this.appState$.dispatch(new SetValueAction(INITIAL_STATE.controls.publicationChannels.id, box(publicationChannels)));
+        });
+    } else {
+      this.appState$.dispatch(gridFailureActions.deletePublicationChannelAssignment({ gridFailureId: this._gridFailureId, channel: channel }));
+      this.actionsSubject.pipe(ofType(gridFailureActions.deletePublicationChannelAssignmentSuccess), takeUntil(this._endSubscriptions$)).subscribe(() => {
+        publicationChannels = publicationChannels.filter((x: string) => x !== channel);
+        this.appState$.dispatch(new SetValueAction(INITIAL_STATE.controls.publicationChannels.id, box(publicationChannels)));
+      });
+    }
+  }
+
   public setSelectedStation(selectedStation: models.FailureStation) {
     this._selectedStation = selectedStation;
   }
@@ -575,7 +624,11 @@
     if (!this._selectedStation) {
       return;
     }
-    if (this.currentFormState.value.stationIds.some(id => id === this._selectedStation.id)) {
+    if (
+      this.currentFormState.value.stationIds &&
+      unbox(this.currentFormState.value.stationIds) &&
+      unbox(this.currentFormState.value.stationIds).some(id => id === this._selectedStation.id)
+    ) {
       this._utilService.displayNotification('SelectedStationAlreadyAssigned', 'alert');
       return;
     }
@@ -585,12 +638,7 @@
       this.latLonMapping({ longitude: this.gridFailureStations[0].longitude, latitude: this.gridFailureStations[0].latitude });
 
     this._calculatePolygon(this.gridFailureStations);
-    this.appState$.dispatch(
-      new SetValueAction(
-        this.currentFormState.controls.stationIds.id,
-        this.gridFailureStations.map(station => station.id)
-      )
-    );
+    this.appState$.dispatch(new SetValueAction(this.currentFormState.controls.stationIds.id, box(this.gridFailureStations.map(station => station.id))));
     this.appState$.dispatch(new MarkAsDirtyAction(this.currentFormState.id));
 
     this.latLonMapping({ longitude: this.gridFailureStations[0].longitude, latitude: this.gridFailureStations[0].latitude });
@@ -604,12 +652,7 @@
       this.resetCoords();
     }
     this.gridFailureStations = this.gridFailureStations.filter(station => station.id != stationId);
-    this.appState$.dispatch(
-      new SetValueAction(
-        this.currentFormState.controls.stationIds.id,
-        this.gridFailureStations.map(station => station.id)
-      )
-    );
+    this.appState$.dispatch(new SetValueAction(this.currentFormState.controls.stationIds.id, box(this.gridFailureStations.map(station => station.id))));
 
     this.appState$.dispatch(new MarkAsDirtyAction(this.currentFormState.id));
 
@@ -627,6 +670,10 @@
     this.appState$.dispatch(new DisableAction(INITIAL_STATE.controls.radiusId.id));
   }
 
+  private _disableStationControls(): void {
+    this.appState$.dispatch(new DisableAction(INITIAL_STATE.controls.stationDescription.id));
+  }
+
   public loadInitialAddressData(formState: FormGroupState<models.GridFailure>) {
     if (!formState.value || !formState.controls) return;
 
@@ -729,6 +776,7 @@
     this.showStornoButton = false;
     this.showCreatedButton = false;
     this.showUpdateButton = false;
+    this.showPublishButton = false;
 
     switch (state) {
       case enums.StateEnum.NEW:
@@ -742,6 +790,7 @@
         break;
       case enums.StateEnum.QUALIFIED:
         this.showUpdateButton = true;
+        this.showPublishButton = true;
         break;
       default:
         break;
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.html b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.html
index a216c5f..ea8c61f 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.html
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.html
@@ -11,33 +11,32 @@
 * SPDX-License-Identifier: EPL-2.0
 ********************************************************************************/ -->
 <div class="card border-0">
-  <div class="card-body">
-    <div class="d-flex justify-content-end select-distribution-group">
-      <select type="text" [(ngModel)]="selectedGroup" class="form-control col-sm-3">
-        <option [value]="selectedGroup" disabled>{{ 'SelectOption' | translate }}</option>
-        <option *ngFor="let item of detailsSandbox.distributionGroups$ | async" [ngValue]="item">{{ item.name }}</option>
-      </select>
-      <button
-        type="button"
-        class="btn btn-success btn-sm assign-button"
-        (click)="detailsSandbox.createDistributionGroupAssignment(selectedGroup); clearSelectedGroup()"
-      >
-        {{ 'GridFailure.AssignGroupBtn' | translate }}
-      </button>
-    </div>
-    <div class="distribution-groups">
-      <ag-grid-angular
-        autoResizeColumns
-        class="ag-theme-balham"
-        [gridOptions]="gridOptions"
-        [columnDefs]="columnDefinition"
-        [rowSelection]="'single'"
-        [frameworkComponents]="frameworkComponents"
-        [rowData]="detailsSandbox.gridFailureDistributionGroups$ | async"
-        [overlayNoRowsTemplate]="noRowsTemplate"
-      >
-      </ag-grid-angular>
-      <app-spinner [isRunning]="detailsSandbox.gridFailureDistributionGroupsLoading$ | async"></app-spinner>
-    </div>
+  <div class="d-flex mb-3 distribution-groups">
+    <h6 class="mr-auto">{{ 'GridFailure.DistributionGroups' | translate }}</h6>
+    <select type="text" [(ngModel)]="selectedGroup" class="form-control col-sm-3">
+      <option [value]="selectedGroup" disabled>{{ 'SelectOption' | translate }}</option>
+      <option *ngFor="let item of detailsSandbox.distributionGroups$ | async" [ngValue]="item">{{ item.name }}</option>
+    </select>
+    <button
+      type="button"
+      class="btn btn-success btn-sm assign-button"
+      (click)="detailsSandbox.createDistributionGroupAssignment(selectedGroup); clearSelectedGroup()"
+    >
+      {{ 'GridFailure.AssignGroupBtn' | translate }}
+    </button>
+  </div>
+  <div class="distribution-group-table">
+    <ag-grid-angular
+      autoResizeColumns
+      class="ag-theme-balham"
+      [gridOptions]="gridOptions"
+      [columnDefs]="columnDefinition"
+      [rowSelection]="'single'"
+      [frameworkComponents]="frameworkComponents"
+      [rowData]="detailsSandbox.gridFailureDistributionGroups$ | async"
+      [overlayNoRowsTemplate]="noRowsTemplate"
+    >
+    </ag-grid-angular>
+    <app-spinner [isRunning]="detailsSandbox.gridFailureDistributionGroupsLoading$ | async"></app-spinner>
   </div>
 </div>
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.scss b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.scss
index acd53f8..ff27166 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.scss
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.scss
@@ -10,7 +10,7 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
-.distribution-groups {
+.distribution-group-table {
   height: 340px;
 }
 .select-distribution-group {
@@ -20,3 +20,6 @@
 .assign-button {
   margin-left: 10px;
 }
+.distribution-groups {
+  margin-top: 15px;
+}
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts
index 3f18216..f428f45 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts
@@ -22,6 +22,7 @@
   FailureHousenumber,
   FailureAddress,
   DistributionGroup,
+  PublicationChannel,
   Polygon,
 } from '@grid-failure-information-app/shared/models';
 
@@ -86,4 +87,8 @@
   static distributionGroupAdapter(response: any): DistributionGroup {
     return new DistributionGroup(response);
   }
+
+  static publicationChannelAdapter(response: any): PublicationChannel {
+    return new PublicationChannel(response);
+  }
 }
diff --git a/projects/grid-failure-information-app/src/app/shared/constants/globals.ts b/projects/grid-failure-information-app/src/app/shared/constants/globals.ts
index 100f9da..31e6c4e 100644
--- a/projects/grid-failure-information-app/src/app/shared/constants/globals.ts
+++ b/projects/grid-failure-information-app/src/app/shared/constants/globals.ts
@@ -31,7 +31,7 @@
     andCondition: 'und',
     orCondition: 'oder',
   };
-  public static PROPERTIES_TO_BOX: string[] = ['addressPolygonPoints', '__formBranch', 'distributionGroupUuids'];
+  public static PROPERTIES_TO_BOX: string[] = ['addressPolygonPoints', '__formBranch', 'distributionGroupUuids', 'stationIds', 'publicationChannels'];
 
   public static BUSINESS_RULE_FIELDS: any = {
     branch: { power: 'S', gas: 'G', telecommunication: 'TK' },
diff --git a/projects/grid-failure-information-app/src/app/shared/models/grid-failure.model.ts b/projects/grid-failure-information-app/src/app/shared/models/grid-failure.model.ts
index d724e0c..109f517 100644
--- a/projects/grid-failure-information-app/src/app/shared/models/grid-failure.model.ts
+++ b/projects/grid-failure-information-app/src/app/shared/models/grid-failure.model.ts
@@ -33,7 +33,7 @@
   public condensedCount: number = null;
   public city: string = null;
   public district: string = null;
-  public distributionGroupUuids: string[] = null;
+  public distributionGroupUuids: Array<string> = null;
   public failureBegin: string = null;
   public failureClassification: string = null;
   public failureClassificationId: string = null;
@@ -49,7 +49,7 @@
   public responsibility: string = null;
   public stationId: string = null;
   public stationDescription: string = null;
-  public stationIds: string[] = [];
+  public stationIds: Array<string> = null;
   public statusExtern: string = null;
   public statusExternId: string = null;
   public statusIntern: string = null;
@@ -71,6 +71,7 @@
   public failureInformationCondensedId: string = null;
   public addressPolygonPoints: Array<[Number, Number]> | Boxed<Array<[Number, Number]>> = null;
   public description: string = null;
+  public publicationChannels: string[] = null;
 
   public constructor(data: any = null) {
     super(data);
diff --git a/projects/grid-failure-information-app/src/app/shared/models/index.ts b/projects/grid-failure-information-app/src/app/shared/models/index.ts
index 72b8f7d..225ae0b 100644
--- a/projects/grid-failure-information-app/src/app/shared/models/index.ts
+++ b/projects/grid-failure-information-app/src/app/shared/models/index.ts
@@ -26,4 +26,5 @@
 export * from './contact.model';
 export * from './settings.model';
 export * from './distribution-group-text-placeholder.model';
+export * from './publication-channel.model';
 export * from './polygon.model';
diff --git a/projects/grid-failure-information-app/src/app/shared/models/publication-channel.model.ts b/projects/grid-failure-information-app/src/app/shared/models/publication-channel.model.ts
new file mode 100644
index 0000000..644ea42
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/shared/models/publication-channel.model.ts
@@ -0,0 +1,23 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+export class PublicationChannel {
+  public failureInformationId: string = null;
+  public publicationChannel: string = null;
+  public published: string = null;
+
+  public constructor(data: any = null) {
+    Object.keys(data || {})
+      .filter(property => this.hasOwnProperty(property))
+      .forEach(property => (this[property] = data[property]));
+  }
+}
diff --git a/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts b/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts
index b839f6a..4bd4dbc 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts
@@ -22,6 +22,7 @@
   FailureHousenumber,
   FailureAddress,
   DistributionGroup,
+  PublicationChannel,
   Polygon,
 } from '@grid-failure-information-app/shared/models';
 
@@ -44,7 +45,7 @@
 export const loadGridFailureDetailSuccess = createAction('[GridFailure Details] Load Success', props<ILoadGridFailureSuccess>());
 export const loadGridFailureDetailFail = createAction('[GridFailure Details] Load Fail', props<{ payload: string }>());
 
-export const saveGridFailure = createAction('[GridFailure Details] Save', props<{ payload: GridFailure }>());
+export const saveGridFailure = createAction('[GridFailure Details] Save', props<{ payload: { gridFailure: GridFailure; saveForPublish: boolean } }>());
 export const saveGridFailureSuccess = createAction('[GridFailure Details] Save Success', props<{ payload: GridFailure }>());
 export const saveGridFailureFail = createAction('[GridFailure Details] Save Fail', props<{ payload: string }>());
 
@@ -160,3 +161,14 @@
 export const deleteDistributionGroupAssignment = createAction('[DistributionGroupAssignment] Delete', props<{ gridFailureId: string; groupId: string }>());
 export const deleteDistributionGroupAssignmentSuccess = createAction('[DistributionGroupAssignment] Delete Success');
 export const deleteDistributionGroupAssignmentFail = createAction('[DistributionGroupAssignment] Delete Fail', props<{ payload: string }>());
+
+export const createPublicationChannelAssignment = createAction('[PublicationChannelAssignment] Create', props<{ gridFailureId: string; channel: string }>());
+export const createPublicationChannelAssignmentSuccess = createAction(
+  '[PublicationChannelAssignment] Create Success',
+  props<{ payload: PublicationChannel }>()
+);
+export const createPublicationChannelAssignmentFail = createAction('[PublicationChannelAssignment] Create Fail', props<{ payload: string }>());
+
+export const deletePublicationChannelAssignment = createAction('[PublicationGroupAssignment] Delete', props<{ gridFailureId: string; channel: string }>());
+export const deletePublicationChannelAssignmentSuccess = createAction('[PublicationChannelAssignment] Delete Success');
+export const deletePublicationChannelAssignmentFail = createAction('[PublicationChannelAssignment] Delete Fail', props<{ payload: string }>());
diff --git a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts
index a209d2a..71f575f 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts
@@ -23,6 +23,7 @@
   FailureStation,
   FailureAddress,
   DistributionGroup,
+  PublicationChannel,
 } from '@grid-failure-information-app/shared/models';
 import * as gridFailureActions from '@grid-failure-information-app/shared/store/actions/grid-failures.action';
 import { GridFailureApiClient } from '@grid-failure-information-app/pages/grid-failure/grid-failure-api-client';
@@ -61,6 +62,8 @@
       getGridFailureDistributionGroups() {},
       postDistributionGroupAssignment() {},
       deleteDistributionGroupAssignment() {},
+      postPublicationChannelAssignment() {},
+      deletePublicationChannelAssignment() {},
       getGridFailureStations() {},
       postGridFailureStation() {},
       deleteGridFailureStation() {},
@@ -122,7 +125,7 @@
       expect(result).toEqual(gridFailureActions.saveGridFailureSuccess({ payload: new GridFailure({ id: '1' }) }));
     });
     done();
-    actions$.next(gridFailureActions.saveGridFailure({ payload: new GridFailure({ id: '1' }) }));
+    actions$.next(gridFailureActions.saveGridFailure({ payload: { gridFailure: new GridFailure({ id: '1' }), saveForPublish: false } }));
   });
 
   it('should equal saveGridFailureFail in response to saveGridFailure Error', done => {
@@ -131,7 +134,7 @@
       expect(result).toEqual(gridFailureActions.saveGridFailureFail({ payload: 'x' }));
     });
     done();
-    actions$.next(gridFailureActions.saveGridFailure({ payload: new GridFailure({ id: '1' }) }));
+    actions$.next(gridFailureActions.saveGridFailure({ payload: { gridFailure: new GridFailure({ id: '1' }), saveForPublish: false } }));
   });
 
   it('should equal loadGridFailureVersionsSuccess after getGridFailureVersions', done => {
@@ -573,6 +576,15 @@
     actions$.next(gridFailureActions.loadGridFailureDistributionGroups({ payload: '1' }));
   });
 
+  it('should dispatch loadGridFailureDistributionGroupsFail action triggered by loadGridFailureDistributionGroups Error', done => {
+    spyOn(apiClient, 'getGridFailureDistributionGroups').and.returnValue(throwError('x'));
+    effects.getGridFailureDistributionGroups$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.loadGridFailureDistributionGroupsFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(gridFailureActions.loadGridFailureDistributionGroups({ payload: '1' }));
+  });
+
   it('should dispatch createDistributionGroupAssignmentSuccess action triggered by createDistributionGroupAssignment action', done => {
     apiResponse = new DistributionGroup({ id: '1' });
     spyOn(apiClient, 'postDistributionGroupAssignment').and.returnValue(of(apiResponse));
@@ -583,6 +595,15 @@
     actions$.next(gridFailureActions.createDistributionGroupAssignment({ gridFailureId: '1', newGroup: new DistributionGroup({ id: '1' }) }));
   });
 
+  it('should dispatch createDistributionGroupAssignmentFail action triggered by createDistributionGroupAssignment Error', done => {
+    spyOn(apiClient, 'postDistributionGroupAssignment').and.returnValue(throwError('x'));
+    effects.createDistributionGroupAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.createDistributionGroupAssignmentFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(gridFailureActions.createDistributionGroupAssignment({ gridFailureId: '1', newGroup: new DistributionGroup({ id: '1' }) }));
+  });
+
   it('should dispatch deleteDistributionGroupAssignmentSuccess action triggered by deleteDistributionGroupAssignment action', done => {
     spyOn(apiClient, 'deleteDistributionGroupAssignment').and.returnValue(of(null));
     effects.deleteDistributionGroupAssignment$.pipe(take(1)).subscribe(result => {
@@ -592,6 +613,52 @@
     actions$.next(gridFailureActions.deleteDistributionGroupAssignment({ gridFailureId: '1', groupId: '2' }));
   });
 
+  it('should dispatch deleteDistributionGroupAssignmentFail action triggered by deleteDistributionGroupAssignment Error', done => {
+    spyOn(apiClient, 'deleteDistributionGroupAssignment').and.returnValue(throwError('x'));
+    effects.deleteDistributionGroupAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.deleteDistributionGroupAssignmentFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(gridFailureActions.deleteDistributionGroupAssignment({ gridFailureId: '1', groupId: '2' }));
+  });
+
+  it('should dispatch createPublicationChannelAssignmentSuccess action triggered by createPublicationChannelAssignment action', done => {
+    apiResponse = new PublicationChannel({ failureInformationId: '1' });
+    spyOn(apiClient, 'postPublicationChannelAssignment').and.returnValue(of(apiResponse));
+    effects.createPublicationChannelAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.createPublicationChannelAssignmentSuccess({ payload: apiResponse }));
+    });
+    done();
+    actions$.next(gridFailureActions.createPublicationChannelAssignment({ gridFailureId: '1', channel: 'SMS' }));
+  });
+
+  it('should dispatch createPublicationChannelAssignmentFail action triggered by createPublicationChannelAssignment Error', done => {
+    spyOn(apiClient, 'postPublicationChannelAssignment').and.returnValue(throwError('x'));
+    effects.createPublicationChannelAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.createPublicationChannelAssignmentFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(gridFailureActions.createPublicationChannelAssignment({ gridFailureId: '1', channel: 'SMS' }));
+  });
+
+  it('should dispatch deletePublicationChannelAssignmentSuccess action triggered by deletePublicationChannelAssignment action', done => {
+    spyOn(apiClient, 'deletePublicationChannelAssignment').and.returnValue(of(null));
+    effects.deletePublicationChannelAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.deletePublicationChannelAssignmentSuccess());
+    });
+    done();
+    actions$.next(gridFailureActions.deletePublicationChannelAssignment({ gridFailureId: '1', channel: 'SMS' }));
+  });
+
+  it('should dispatch deletePublicationChannelAssignmentFail action triggered by deletePublicationChannelAssignment Error', done => {
+    spyOn(apiClient, 'deletePublicationChannelAssignment').and.returnValue(throwError('x'));
+    effects.deletePublicationChannelAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.deletePublicationChannelAssignmentFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(gridFailureActions.deletePublicationChannelAssignment({ gridFailureId: '1', channel: 'SMS' }));
+  });
+
   it('should equal loadGridFailurePolygon in response to getGridFailurePolygon', done => {
     apiResponse = [
       [1, 1],
diff --git a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts
index 4f91c4b..15e1c52 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts
@@ -63,8 +63,11 @@
     this._actions$.pipe(
       ofType(gridFailureActions.saveGridFailure),
       map(action => action['payload']),
-      exhaustMap((payload: GridFailure) => {
-        return (payload.id ? this._apiClient.putGridFailure(payload.id, payload) : this._apiClient.postGridFailure(payload)).pipe(
+      exhaustMap((payload: { gridFailure: GridFailure; saveForPublish: boolean }) => {
+        return (payload.gridFailure.id
+          ? this._apiClient.putGridFailure(payload.gridFailure.id, payload.gridFailure, payload.saveForPublish)
+          : this._apiClient.postGridFailure(payload.gridFailure)
+        ).pipe(
           map((item: GridFailure) => {
             this._store.dispatch(gridFailureActions.loadGridFailures());
             return gridFailureActions.saveGridFailureSuccess({ payload: item });
@@ -398,5 +401,33 @@
     )
   );
 
+  createPublicationChannelAssignment$: any = createEffect(() =>
+    this._actions$.pipe(
+      ofType(gridFailureActions.createPublicationChannelAssignment),
+      switchMap(action => {
+        return this._apiClient.postPublicationChannelAssignment(action.gridFailureId, action.channel).pipe(
+          map(item => {
+            return gridFailureActions.createPublicationChannelAssignmentSuccess({ payload: item });
+          }),
+          catchError(error => of(gridFailureActions.createPublicationChannelAssignmentFail({ payload: error })))
+        );
+      })
+    )
+  );
+
+  deletePublicationChannelAssignment$: any = createEffect(() =>
+    this._actions$.pipe(
+      ofType(gridFailureActions.deletePublicationChannelAssignment),
+      switchMap(action => {
+        return this._apiClient.deletePublicationChannelAssignment(action.gridFailureId, action.channel).pipe(
+          map(item => {
+            return gridFailureActions.deletePublicationChannelAssignmentSuccess();
+          }),
+          catchError(error => of(gridFailureActions.deletePublicationChannelAssignmentFail({ payload: error })))
+        );
+      })
+    )
+  );
+
   constructor(private _actions$: Actions, private _apiClient: GridFailureApiClient, private _store: Store<any>) {}
 }
diff --git a/projects/grid-failure-information-app/src/app/shared/store/index.ts b/projects/grid-failure-information-app/src/app/shared/store/index.ts
index a39c63f..eb9b659 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/index.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/index.ts
@@ -118,6 +118,7 @@
 export const getAvailableLanguages = createSelector(getSettingsState, fromSettings.getAvailableLanguages);
 export const getUser = createSelector(getSettingsState, fromSettings.getUser);
 export const getPreConfiguration = createSelector(getSettingsState, fromSettings.getPreConfiguration);
+export const getExportChannels = createSelector(getSettingsState, fromSettings.getExportChannels);
 
 /**
  * GridFailures store functions
diff --git a/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer.ts b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer.ts
index 972d42d..c4b8aa4 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer.ts
@@ -191,6 +191,9 @@
       housenumber: (propState, formState): any => {
         return requiredIf(propState, formState, formState.controls.branchId.id, NO_BRANCH_ID_KEY);
       },
+      radiusId: (propState, formState): any => {
+        return requiredIf(propState, formState, formState.controls.branchId.id, NO_BRANCH_ID_KEY);
+      },
       voltageLevel: (propState, formState): any => {
         return requiredIf(propState, formState, formState.controls.branchId.id, GAS_BRANCH_ID_KEY);
       },
@@ -204,7 +207,6 @@
       branchId: validate(required),
       failureBegin: validate(required),
       expectedReasonId: validate(required),
-      radiusId: validate(required),
       longitude: validate(required),
       latitude: validate(required),
       __formBranch: validate(required),
diff --git a/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.spec.ts b/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.spec.ts
index 46e5846..b955f7c 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.spec.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.spec.ts
@@ -18,6 +18,8 @@
   getSelectedCulture,
   getAvailableLanguages,
   getUser,
+  getPreConfiguration,
+  getExportChannels,
 } from '@grid-failure-information-app/shared/store/reducers/settings.reducer';
 import * as settingsActions from '@grid-failure-information-app/shared/store/actions/settings.action';
 import { User } from '@grid-failure-information-app/shared/models/user';
@@ -51,16 +53,6 @@
     });
   });
 
-  it('should set culture', () => {
-    const action = settingsActions.setCulture({ payload: 'DE-de' });
-    const result = settingsReducer(INITIAL_STATE, action);
-
-    expect(result).toEqual({
-      ...INITIAL_STATE,
-      selectedCulture: 'DE-de',
-    });
-  });
-
   it('should set User', () => {
     const user = new User();
     user.name = 'Max Muster';
@@ -73,6 +65,28 @@
     });
   });
 
+  it('should return loading state for loadPreConfiguration', () => {
+    const action = settingsActions.loadPreConfiguration();
+    const result = settingsReducer(INITIAL_STATE, action);
+
+    expect(result.preConfiguration.loading).toBeTruthy();
+  });
+
+  it('should return loaded state for loadPreConfigurationSuccess', () => {
+    const settings = new Settings();
+    const action = settingsActions.loadPreConfigurationSuccess({ payload: settings });
+    const result = settingsReducer(INITIAL_STATE, action);
+
+    expect(result.preConfiguration.loaded).toBeTruthy();
+  });
+
+  it('should return failed state for loadPreConfigurationFail', () => {
+    const action = settingsActions.loadPreConfigurationFail({ payload: 'error' });
+    const result = settingsReducer(INITIAL_STATE, action);
+
+    expect(result.preConfiguration.failed).toBeTruthy();
+  });
+
   it('getSelectedLanguage should return state.selectedLanguage', () => {
     const state = { ...INITIAL_STATE };
     const result = getSelectedLanguage(state);
@@ -96,4 +110,10 @@
     const result = getUser(state);
     expect(result).toBe(state.user);
   });
+
+  it('getPreConfiguration should return state.getPreConfiguration.data', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getPreConfiguration(state);
+    expect(result).toBe(state.preConfiguration.data);
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.ts b/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.ts
index 4e2e8a5..4629f53 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/reducers/settings.reducer.ts
@@ -98,3 +98,4 @@
 export const getAvailableLanguages = (state: State) => state.availableLanguages;
 export const getUser = (state: State) => state.user;
 export const getPreConfiguration = (state: State) => state.preConfiguration.data;
+export const getExportChannels = (state: State) => state.preConfiguration.data.exportChannels;