diff --git a/package-lock.json b/package-lock.json
index 855d5327d5bcf4e69e2e250a5e08a9f548eeb620..e72bbc7c77242c6fbd767fdb419fff165e631c53 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2301,6 +2301,15 @@
       "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
       "dev": true
     },
+    "camel-case": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+      "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+      "requires": {
+        "no-case": "^2.2.0",
+        "upper-case": "^1.1.1"
+      }
+    },
     "camelcase": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
@@ -2357,6 +2366,31 @@
         }
       }
     },
+    "change-case": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.1.0.tgz",
+      "integrity": "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==",
+      "requires": {
+        "camel-case": "^3.0.0",
+        "constant-case": "^2.0.0",
+        "dot-case": "^2.1.0",
+        "header-case": "^1.0.0",
+        "is-lower-case": "^1.1.0",
+        "is-upper-case": "^1.1.0",
+        "lower-case": "^1.1.1",
+        "lower-case-first": "^1.0.0",
+        "no-case": "^2.3.2",
+        "param-case": "^2.1.0",
+        "pascal-case": "^2.0.0",
+        "path-case": "^2.1.0",
+        "sentence-case": "^2.1.0",
+        "snake-case": "^2.1.0",
+        "swap-case": "^1.1.0",
+        "title-case": "^2.1.0",
+        "upper-case": "^1.1.1",
+        "upper-case-first": "^1.1.0"
+      }
+    },
     "chardet": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
@@ -2734,6 +2768,15 @@
       "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
       "dev": true
     },
+    "constant-case": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz",
+      "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=",
+      "requires": {
+        "snake-case": "^2.1.0",
+        "upper-case": "^1.1.1"
+      }
+    },
     "constants-browserify": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
@@ -4080,6 +4123,14 @@
         "domelementtype": "1"
       }
     },
+    "dot-case": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz",
+      "integrity": "sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=",
+      "requires": {
+        "no-case": "^2.2.0"
+      }
+    },
     "dot-prop": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz",
@@ -6307,6 +6358,15 @@
         "minimalistic-assert": "^1.0.1"
       }
     },
+    "header-case": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz",
+      "integrity": "sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=",
+      "requires": {
+        "no-case": "^2.2.0",
+        "upper-case": "^1.1.3"
+      }
+    },
     "hmac-drbg": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -6945,6 +7005,14 @@
         "is-extglob": "^2.1.1"
       }
     },
+    "is-lower-case": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz",
+      "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=",
+      "requires": {
+        "lower-case": "^1.1.0"
+      }
+    },
     "is-number": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -7049,6 +7117,14 @@
       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
       "dev": true
     },
+    "is-upper-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz",
+      "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=",
+      "requires": {
+        "upper-case": "^1.1.0"
+      }
+    },
     "is-utf8": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
@@ -7841,6 +7917,19 @@
         "signal-exit": "^3.0.0"
       }
     },
+    "lower-case": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+      "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
+    },
+    "lower-case-first": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz",
+      "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=",
+      "requires": {
+        "lower-case": "^1.1.2"
+      }
+    },
     "lru-cache": {
       "version": "4.1.5",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@@ -8380,6 +8469,14 @@
       "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
       "dev": true
     },
+    "no-case": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+      "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+      "requires": {
+        "lower-case": "^1.1.1"
+      }
+    },
     "node-fetch-npm": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz",
@@ -9113,6 +9210,14 @@
         "readable-stream": "^2.1.5"
       }
     },
+    "param-case": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
+      "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
+      "requires": {
+        "no-case": "^2.2.0"
+      }
+    },
     "parse-asn1": {
       "version": "5.1.4",
       "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz",
@@ -9201,6 +9306,15 @@
       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
       "dev": true
     },
+    "pascal-case": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz",
+      "integrity": "sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=",
+      "requires": {
+        "camel-case": "^3.0.0",
+        "upper-case-first": "^1.1.0"
+      }
+    },
     "pascalcase": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
@@ -9234,6 +9348,14 @@
       "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
       "dev": true
     },
+    "path-case": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz",
+      "integrity": "sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=",
+      "requires": {
+        "no-case": "^2.2.0"
+      }
+    },
     "path-dirname": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
@@ -10368,6 +10490,15 @@
         }
       }
     },
+    "sentence-case": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz",
+      "integrity": "sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=",
+      "requires": {
+        "no-case": "^2.2.0",
+        "upper-case-first": "^1.1.2"
+      }
+    },
     "serialize-javascript": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz",
@@ -10541,6 +10672,14 @@
       "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==",
       "dev": true
     },
+    "snake-case": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz",
+      "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=",
+      "requires": {
+        "no-case": "^2.2.0"
+      }
+    },
     "snapdragon": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -11612,6 +11751,15 @@
         "has-flag": "^3.0.0"
       }
     },
+    "swap-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz",
+      "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=",
+      "requires": {
+        "lower-case": "^1.1.1",
+        "upper-case": "^1.1.1"
+      }
+    },
     "symbol-observable": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
@@ -11869,6 +12017,15 @@
         "setimmediate": "^1.0.4"
       }
     },
+    "title-case": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz",
+      "integrity": "sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=",
+      "requires": {
+        "no-case": "^2.2.0",
+        "upper-case": "^1.0.3"
+      }
+    },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -12229,6 +12386,19 @@
       "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
       "dev": true
     },
+    "upper-case": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+      "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
+    },
+    "upper-case-first": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz",
+      "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=",
+      "requires": {
+        "upper-case": "^1.1.1"
+      }
+    },
     "uri-js": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
diff --git a/package.json b/package.json
index e8d9b1398e35637a52bc65a8a264bd1c1fd840eb..33a2143ee985e0bc0f96d2267974a05f25f0bbe0 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
     "@ngxs/logger-plugin": "3.4.3",
     "@ngxs/router-plugin": "3.4.3",
     "@ngxs/store": "3.4.3",
+    "change-case": "^3.1.0",
     "core-js": "2.5.4",
     "decimal.js": "10.2.0",
     "flexboxgrid-sass": "8.0.5",
diff --git a/src/app/organizational-unit/components/form/form.component.ts b/src/app/organizational-unit/components/form/form.component.ts
index dbb4c2e035043e7c1efdf9287d10e21c779f182f..686253bdaccbf5ee981bc65256db0c0449910365 100644
--- a/src/app/organizational-unit/components/form/form.component.ts
+++ b/src/app/organizational-unit/components/form/form.component.ts
@@ -2,6 +2,7 @@ import {ChangeDetectionStrategy, Component, Input} from "@angular/core";
 import {FormBuilder, Validators} from "@angular/forms";
 import {OrganizationalUnitsModel, PreservationPoliciesModel, SubmissionPoliciesModel} from "@app/generated-api";
 import {AbstractFormComponent} from "@app/shared/components/abstract-form/abstract-form.component";
+import {ModelAttributEnum} from "@app/shared/enums/model-attribut.enum";
 import {DateUtil} from "@app/shared/utils/date.util";
 import _ from "lodash";
 
@@ -53,7 +54,7 @@ export class FormComponent extends AbstractFormComponent<OrganizationalUnitsMode
       closingDate: [organizationalUnit.closingDate],
       isEmpty: [organizationalUnit.isEmpty],
       open: [organizationalUnit.open],
-      submissionPolicies: [_.map(this.selectedSubmissionPolicies, "resId")],
+      submissionPolicies: [_.map(this.selectedSubmissionPolicies, ModelAttributEnum.resId)],
     });
   }
 
diff --git a/src/app/organizational-unit/views/detail/detail.view.ts b/src/app/organizational-unit/views/detail/detail.view.ts
index 2f1d915bece01a3c366fb438cc694cf3b5050018..c4f38c22463492d149f9b2d61d812ecfd338c80d 100644
--- a/src/app/organizational-unit/views/detail/detail.view.ts
+++ b/src/app/organizational-unit/views/detail/detail.view.ts
@@ -20,7 +20,7 @@ import {Observable} from "rxjs";
   changeDetection: ChangeDetectionStrategy.OnPush,
 })
 export class DetailView extends AbstractDetailView<OrganizationalUnitsModel, OrganizationalUnitStateModel> {
-  @Select((state) => (state[StateEnum.organizationalUnit] as OrganizationalUnitStateModel).listSubmissionPolicies) selectedSubmissionPolicies$: Observable<SubmissionPoliciesModel[]>;
+  @Select((state) => (state[StateEnum.organizationalUnit] as OrganizationalUnitStateModel).selectedSubmissionPolicies) selectedSubmissionPolicies$: Observable<SubmissionPoliciesModel[]>;
   @Select((state) => ((state[StateEnum.shared] as SharedStateModel).submissionPolicy as SubmissionPolicyStateModel).list) listSubmissionPolicies$: Observable<SubmissionPoliciesModel[]>;
   @Select((state) => ((state[StateEnum.shared] as SharedStateModel).preservationPolicy as PreservationPolicyStateModel).list) listPreservationPolicies$: Observable<PreservationPoliciesModel[]>;
 
@@ -35,6 +35,6 @@ export class DetailView extends AbstractDetailView<OrganizationalUnitsModel, Org
   }
 
   getSubResourceWithParentId(id: string): void {
-    this.store.dispatch(new OrgUnitAction.GetAllSubmissionPolicy(id));
+    this.store.dispatch(new OrgUnitAction.GetAllSubResourceSubmissionPolicies(id));
   }
 }
diff --git a/src/app/organizational-unit/views/edit/edit.view.ts b/src/app/organizational-unit/views/edit/edit.view.ts
index 89e937ca3d33402c2a568ea5a9a39c5a74372ad1..932455418cb210836d9cafd8f9c4e0f9ef712829 100644
--- a/src/app/organizational-unit/views/edit/edit.view.ts
+++ b/src/app/organizational-unit/views/edit/edit.view.ts
@@ -19,7 +19,7 @@ import {Observable} from "rxjs";
 })
 export class EditView extends AbstractEditView<OrganizationalUnitsModel, OrganizationalUnitStateModel> {
   @Select((state) => (state[StateEnum.organizationalUnit] as OrganizationalUnitStateModel).isLoadingSubmissionPolicies) isLoadingSubmissionPolicies$: Observable<boolean>;
-  @Select((state) => (state[StateEnum.organizationalUnit] as OrganizationalUnitStateModel).listSubmissionPolicies) selectedSubmissionPolicies$: Observable<SubmissionPoliciesModel[]>;
+  @Select((state) => (state[StateEnum.organizationalUnit] as OrganizationalUnitStateModel).selectedSubmissionPolicies) selectedSubmissionPolicies$: Observable<SubmissionPoliciesModel[]>;
   @Select((state) => ((state[StateEnum.shared] as SharedStateModel).submissionPolicy as SubmissionPolicyStateModel).list) listSubmissionPolicies$: Observable<SubmissionPoliciesModel[]>;
   @Select((state) => ((state[StateEnum.shared] as SharedStateModel).preservationPolicy as PreservationPolicyStateModel).list) listPreservationPolicies$: Observable<PreservationPoliciesModel[]>;
 
@@ -29,6 +29,6 @@ export class EditView extends AbstractEditView<OrganizationalUnitsModel, Organiz
   }
 
   getSubresourceWithParentId(id: string): void {
-    this.store.dispatch(new OrgUnitAction.GetAllSubmissionPolicy(id));
+    this.store.dispatch(new OrgUnitAction.GetAllSubResourceSubmissionPolicies(id));
   }
 }
diff --git a/src/app/shared/components/abstract-form/abstract-form.component.ts b/src/app/shared/components/abstract-form/abstract-form.component.ts
index a043f71598f404b3dd34ffd80747f4479f45fc32..4073ffff43023d1f1ac18dc2ae89ee0db8ea976c 100644
--- a/src/app/shared/components/abstract-form/abstract-form.component.ts
+++ b/src/app/shared/components/abstract-form/abstract-form.component.ts
@@ -1,6 +1,7 @@
 import {EventEmitter, Input, OnInit, Output} from "@angular/core";
 import {AbstractControl, FormGroup, Validators} from "@angular/forms";
 import {BaseDirective} from "@app/shared/directives/base.directive";
+import {ModelAttributEnum} from "@app/shared/enums/model-attribut.enum";
 
 export abstract class AbstractFormComponent<T> extends BaseDirective implements OnInit {
   public form: FormGroup;
@@ -52,7 +53,7 @@ export abstract class AbstractFormComponent<T> extends BaseDirective implements
   private addResId(model: T) {
     const isUpdate = this.model !== null && this.model !== undefined;
     if (isUpdate) {
-      model["resId"] = this.model["resId"];
+      model[ModelAttributEnum.resId] = this.model[ModelAttributEnum.resId];
     }
   }
 
diff --git a/src/app/shared/crud.action.ts b/src/app/shared/crud.action.ts
index 6dbf2b8be65c33cf9cd94a96039d21fc7436ec63..d892663da68a276f3259190bcd8c49f07dc25020 100644
--- a/src/app/shared/crud.action.ts
+++ b/src/app/shared/crud.action.ts
@@ -131,24 +131,96 @@ export namespace CrudAction {
   }
 
   export class GetAllSubResource {
-    protected static abstractType = "[{0}] Get All Subresource {1}";
-    public static readonly className = "GetAllSubResource";
+    protected static abstractType = "[{0}] Get All SubResource {1}";
+    public static readonly className = "GetAllSubResource{0}";
 
     constructor(public parentId: string, public queryParameters?: QueryParametersModel) {
     }
   }
 
   export class GetAllSubResourceSuccess<T> {
-    protected static abstractType = "[{0}] Get All Subresource {1} Success";
-    public static readonly className = "GetAllSubResourceSuccess";
+    protected static abstractType = "[{0}] Get All SubResource {1} Success";
+    public static readonly className = "GetAllSubResource{0}Success";
 
     constructor(public list: CollectionTypedModel<T>) {
     }
   }
 
   export class GetAllSubResourceFail {
-    protected static abstractType = "[{0}] Get All Subresource {1} Fail";
-    public static readonly className = "GetAllSubResourceFail";
+    protected static abstractType = "[{0}] Get All SubResource {1} Fail";
+    public static readonly className = "GetAllSubResource{0}Fail";
+
+    constructor() {
+    }
+  }
+
+  export class CreateSubResource {
+    protected static abstractType = "[{0}] Create SubResource {1}";
+    public static readonly className = "CreateSubResource{0}";
+
+    constructor(public parentId: string, public listResId: string[]) {
+    }
+  }
+
+  export class CreateSubResourceSuccess {
+    protected static abstractType = "[{0}] Create SubResource {1} Success";
+    public static readonly className = "CreateSubResource{0}Success";
+
+    constructor() {
+    }
+  }
+
+  export class CreateSubResourceFail {
+    protected static abstractType = "[{0}] Create SubResource {1} Fail";
+    public static readonly className = "CreateSubResource{0}Fail";
+
+    constructor() {
+    }
+  }
+
+  export class DeleteSubResource {
+    protected static abstractType = "[{0}] Delete SubResource {1}";
+    public static readonly className = "DeleteSubResource{0}";
+
+    constructor(public parentId: string, public listResId: string[]) {
+    }
+  }
+
+  export class DeleteSubResourceSuccess {
+    protected static abstractType = "[{0}] Delete SubResource {1} Success";
+    public static readonly className = "DeleteSubResource{0}Success";
+
+    constructor() {
+    }
+  }
+
+  export class DeleteSubResourceFail {
+    protected static abstractType = "[{0}] Delete SubResource {1} Fail";
+    public static readonly className = "DeleteSubResource{0}Fail";
+
+    constructor() {
+    }
+  }
+
+  export class UpdateSubResource {
+    protected static abstractType = "[{0}] Update SubResource {1}";
+    public static readonly className = "UpdateSubResource{0}";
+
+    constructor(public parentId: string, public oldResId: string[], public newResId: string[]) {
+    }
+  }
+
+  export class UpdateSubResourceSuccess {
+    protected static abstractType = "[{0}] Update SubResource {1} Success";
+    public static readonly className = "UpdateSubResource{0}Success";
+
+    constructor() {
+    }
+  }
+
+  export class UpdateSubResourceFail {
+    protected static abstractType = "[{0}] Update SubResource {1} Fail";
+    public static readonly className = "UpdateSubResource{0}Fail";
 
     constructor() {
     }
diff --git a/src/app/shared/crud.state.ts b/src/app/shared/crud.state.ts
index 099b96004b7a1dac084bf777f9ab93b8fbd0cabd..e0672424b34e4a619241aa640b85ea11d2c6c7e7 100644
--- a/src/app/shared/crud.state.ts
+++ b/src/app/shared/crud.state.ts
@@ -2,10 +2,12 @@ import {BaseStateModel} from "@app/base.state";
 import {CrudAction} from "@app/shared/crud.action";
 import {ApiResourceNameEnum} from "@app/shared/enums/api-resource-name.enum";
 import {ResourceApiEnum, SubResourceApiEnum} from "@app/shared/enums/api.enum";
+import {ModelAttributEnum} from "@app/shared/enums/model-attribut.enum";
 import {urlSeparator} from "@app/shared/enums/routes.enum";
 import {StateEnum} from "@app/shared/enums/state.enum";
 import {CollectionTypedModel} from "@app/shared/models/collection-typed.model";
 import {QueryParametersModel} from "@app/shared/models/query-parameters.model";
+import {SubResourceUpdateModel} from "@app/shared/models/sub-resource-update.model";
 import {ApiService} from "@app/shared/services/api.service";
 import {NotificationService} from "@app/shared/services/notification.service";
 import {CrudActionUtil} from "@app/shared/utils/crud-action.util";
@@ -15,6 +17,7 @@ import {ObjectUtil} from "@app/shared/utils/object.util";
 import {TRANSLATE} from "@app/shared/utils/translate.util";
 import {Navigate} from "@ngxs/router-plugin";
 import {StateContext} from "@ngxs/store";
+import _ from "lodash";
 import {Observable} from "rxjs";
 import {catchError} from "rxjs/internal/operators/catchError";
 import {tap} from "rxjs/operators";
@@ -27,7 +30,7 @@ export interface CrudStateModel<T> extends BaseStateModel {
 }
 
 export abstract class CrudState<T> {
-  private readonly state: StateEnum;
+  protected readonly state: StateEnum;
   private readonly urlResource: ResourceApiEnum;
   private readonly subResource: ApiResourceNameEnum[];
 
@@ -156,7 +159,7 @@ export abstract class CrudState<T> {
       isLoading: true,
     });
 
-    return this.apiService.patchById<T>(this.urlResource, action.model["resId"], action.model)
+    return this.apiService.patchById<T>(this.urlResource, action.model[ModelAttributEnum.resId], action.model)
       .pipe(
         tap(() => {
           ctx.dispatch(CrudActionUtil.updateSuccess(this.state));
@@ -220,15 +223,41 @@ export abstract class CrudState<T> {
   getAllSubResource<U>(ctx: StateContext<CrudStateModel<T>>, action: CrudAction.GetAllSubResource, subResource: SubResourceApiEnum, parentId: string): Observable<CollectionTypedModel<U>> {
     const queryParameters = CrudHelperUtil.getQueryParametersToApply(action.queryParameters, ctx);
     const url = this.evaluateSubResourceUrl(subResource, parentId);
-    debugger;
-    return null;
     return this.apiService.get<U>(url, queryParameters)
       .pipe(
         tap((collection: CollectionTypedModel<U>) => {
-          // ctx.dispatch(CrudAction.GetAllSubResourceSuccess.getInstance<U>(this.state, subResource, collection));
+          ctx.dispatch(CrudActionUtil.getAllSubResourceSuccess<U>(this.state, subResource, collection));
         }),
         catchError(error => {
-          // ctx.dispatch(CrudAction.GetAllSubResourceFail.getInstance(this.state, subResource));
+          ctx.dispatch(CrudActionUtil.getAllSubResourceFail(this.state, subResource));
+          throw error;
+        }),
+      );
+  }
+
+  createSubResource(ctx: StateContext<CrudStateModel<T>>, action: CrudAction.CreateSubResource, subResource: SubResourceApiEnum, parentId: string): Observable<string[]> {
+    const url = this.evaluateSubResourceUrl(subResource, parentId);
+    return this.apiService.post<string[]>(url, action.listResId)
+      .pipe(
+        tap(() => {
+          ctx.dispatch(CrudActionUtil.createSubResourceSuccess(this.state, subResource));
+        }),
+        catchError(error => {
+          ctx.dispatch(CrudActionUtil.createSubResourceFail(this.state, subResource));
+          throw error;
+        }),
+      );
+  }
+
+  deleteSubResource(ctx: StateContext<CrudStateModel<T>>, action: CrudAction.DeleteSubResource, subResource: SubResourceApiEnum, parentId: string): Observable<string[]> {
+    const url = this.evaluateSubResourceUrl(subResource, parentId);
+    return this.apiService.delete<string[]>(url, action.listResId)
+      .pipe(
+        tap(() => {
+          ctx.dispatch(CrudActionUtil.deleteSubResourceSuccess(this.state, subResource));
+        }),
+        catchError(error => {
+          ctx.dispatch(CrudActionUtil.deleteSubResourceFail(this.state, subResource));
           throw error;
         }),
       );
@@ -237,4 +266,36 @@ export abstract class CrudState<T> {
   private evaluateSubResourceUrl(subResource: ApiResourceNameEnum, parentId: string): string {
     return this.urlResource + urlSeparator + parentId + urlSeparator + subResource;
   }
+
+  updateSubResource(ctx: StateContext<CrudStateModel<T>>, action: CrudAction.UpdateSubResource, subResource: SubResourceApiEnum, parentId: string): void {
+    const subResourceUpdate: SubResourceUpdateModel = this.determineSubResourceChange(action.oldResId, action.newResId);
+    const createAndUpdateActions = this.computeUpdatesActionsToDispatch(subResourceUpdate, subResource, parentId);
+    ctx.dispatch(createAndUpdateActions);
+  }
+
+  private computeUpdatesActionsToDispatch(subResourceUpdate: SubResourceUpdateModel, subResource: SubResourceApiEnum, parentId: string): CrudAction.CreateSubResource[] | CrudAction.DeleteSubResource[] {
+    const actions = [];
+    if (subResourceUpdate.resourceToRemoved.length > 0) {
+      const deleteAction = CrudActionUtil.deleteSubResource(this.state, subResource, parentId, subResourceUpdate.resourceToRemoved);
+      actions.push(deleteAction);
+    }
+    if (subResourceUpdate.resourceToAdd.length > 0) {
+      const createAction = CrudActionUtil.createSubResource(this.state, subResource, parentId, subResourceUpdate.resourceToAdd);
+      actions.push(createAction);
+    }
+    return actions;
+  }
+
+  private determineSubResourceChange(oldSubmissionPolicies, newSubmissionPolicies): SubResourceUpdateModel {
+    const subResourceUpdate: SubResourceUpdateModel = new SubResourceUpdateModel();
+    const diff: string[] = _.xor(oldSubmissionPolicies, newSubmissionPolicies);
+    diff.forEach(d => {
+      if (_.includes(oldSubmissionPolicies, d)) {
+        subResourceUpdate.resourceToRemoved.push(d);
+      } else {
+        subResourceUpdate.resourceToAdd.push(d);
+      }
+    });
+    return subResourceUpdate;
+  }
 }
diff --git a/src/app/shared/enums/model-attribut.enum.ts b/src/app/shared/enums/model-attribut.enum.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eebbe28bc11ca5ca812fa9ec27b2369d944957a6
--- /dev/null
+++ b/src/app/shared/enums/model-attribut.enum.ts
@@ -0,0 +1,3 @@
+export enum ModelAttributEnum {
+  resId = "resId",
+}
diff --git a/src/app/shared/models/sub-resource-update.model.ts b/src/app/shared/models/sub-resource-update.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b8496ed1846dad41fa4d70f811c552631381523
--- /dev/null
+++ b/src/app/shared/models/sub-resource-update.model.ts
@@ -0,0 +1,9 @@
+export class SubResourceUpdateModel {
+  resourceToAdd: string[];
+  resourceToRemoved: string[];
+
+  constructor() {
+    this.resourceToAdd = [];
+    this.resourceToRemoved = [];
+  }
+}
diff --git a/src/app/shared/organizational-unit.action.ts b/src/app/shared/organizational-unit.action.ts
index 3497d4767139cbb6e5f4ef18b01cc45d7e44a8ec..1cb38c37c38dbb3a874928aef0c0bf0b876fd0ec 100644
--- a/src/app/shared/organizational-unit.action.ts
+++ b/src/app/shared/organizational-unit.action.ts
@@ -137,7 +137,7 @@ export namespace OrgUnitAction {
     }
   }
 
-  export class GetAllSubmissionPolicy extends CrudAction.GetAllSubResource {
+  export class GetAllSubResourceSubmissionPolicies extends CrudAction.GetAllSubResource {
     static readonly type = StringUtil.format(CrudAction.GetAllSubResource.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
 
     constructor(public parentId, public queryParameters?: QueryParametersModel) {
@@ -145,16 +145,72 @@ export namespace OrgUnitAction {
     }
   }
 
-  export class GetAllSubmissionPolicySuccess extends CrudAction.GetAllSubResourceSuccess<SubmissionPoliciesModel> {
-    static readonly type = StringUtil.format(CrudAction.GetAllSubResourceSuccess.abstractType, state);
+  export class GetAllSubResourceSubmissionPoliciesSuccess extends CrudAction.GetAllSubResourceSuccess<SubmissionPoliciesModel> {
+    static readonly type = StringUtil.format(CrudAction.GetAllSubResourceSuccess.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
 
     constructor(public list: CollectionTypedModel<SubmissionPoliciesModel>) {
       super(list);
     }
   }
 
-  export class GetAllSubmissionPolicyFail extends CrudAction.GetAllSubResourceFail {
-    static readonly type = StringUtil.format(CrudAction.GetAllSubResourceFail.abstractType, state);
+  export class GetAllSubResourceSubmissionPoliciesFail extends CrudAction.GetAllSubResourceFail {
+    static readonly type = StringUtil.format(CrudAction.GetAllSubResourceFail.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
+
+    constructor() {
+      super();
+    }
+  }
+
+  export class UpdateSubResourceSubmissionPolicies extends CrudAction.UpdateSubResource {
+    static readonly type = StringUtil.format(CrudAction.UpdateSubResource.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
+
+    constructor(public parentId, public oldResId: string[], newResId: string[]) {
+      super(parentId, oldResId, newResId);
+    }
+  }
+
+  export class CreateSubResourceSubmissionPolicies extends CrudAction.CreateSubResource {
+    static readonly type = StringUtil.format(CrudAction.CreateSubResource.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
+
+    constructor(public parentId, public listResId: string[]) {
+      super(parentId, listResId);
+    }
+  }
+
+  export class CreateSubResourceSubmissionPoliciesSuccess extends CrudAction.CreateSubResourceSuccess {
+    static readonly type = StringUtil.format(CrudAction.CreateSubResourceSuccess.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
+
+    constructor() {
+      super();
+    }
+  }
+
+  export class CreateSubResourceSubmissionPoliciesFail extends CrudAction.CreateSubResourceFail {
+    static readonly type = StringUtil.format(CrudAction.CreateSubResourceFail.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
+
+    constructor() {
+      super();
+    }
+  }
+
+  export class DeleteSubResourceSubmissionPolicies extends CrudAction.DeleteSubResource {
+    static readonly type = StringUtil.format(CrudAction.DeleteSubResource.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
+
+    constructor(public parentId, public listResId: string[]) {
+      super(parentId, listResId);
+    }
+  }
+
+  export class DeleteSubResourceSubmissionPoliciesSuccess extends CrudAction.DeleteSubResourceSuccess {
+    static readonly type = StringUtil.format(CrudAction.DeleteSubResourceSuccess.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
+
+    constructor() {
+      super();
+    }
+  }
+
+  export class DeleteSubResourceSubmissionPoliciesFail extends CrudAction.DeleteSubResourceFail {
+    static readonly type = StringUtil.format(CrudAction.DeleteSubResourceFail.abstractType, state, ApiResourceNameEnum.SUB_POLICY);
 
     constructor() {
       super();
diff --git a/src/app/shared/organizational-unit.state.ts b/src/app/shared/organizational-unit.state.ts
index 83024a6060814a2ee9667453a39f0b304f896ced..f77e032a6b2736122d63ffca567684354eb7b331 100644
--- a/src/app/shared/organizational-unit.state.ts
+++ b/src/app/shared/organizational-unit.state.ts
@@ -2,19 +2,22 @@ import {OrganizationalUnitsModel, SubmissionPoliciesModel} from "@app/generated-
 import {CrudState, CrudStateModel} from "@app/shared/crud.state";
 import {ApiResourceNameEnum} from "@app/shared/enums/api-resource-name.enum";
 import {AdminResourceApiEnum, ResourceApiEnum} from "@app/shared/enums/api.enum";
+import {ModelAttributEnum} from "@app/shared/enums/model-attribut.enum";
 import {StateEnum} from "@app/shared/enums/state.enum";
 import {CollectionTypedModel} from "@app/shared/models/collection-typed.model";
 import {QueryParametersModel} from "@app/shared/models/query-parameters.model";
 import {OrgUnitAction} from "@app/shared/organizational-unit.action";
 
 import {ApiService} from "@app/shared/services/api.service";
+import {CrudActionUtil} from "@app/shared/utils/crud-action.util";
 import {NotificationService} from "@app/shared/services/notification.service";
 import {Action, State, StateContext} from "@ngxs/store";
 import _ from "lodash";
 import {Observable} from "rxjs";
+import {tap} from "rxjs/internal/operators/tap";
 
 export interface OrganizationalUnitStateModel extends CrudStateModel<OrganizationalUnitsModel> {
-  listSubmissionPolicies: SubmissionPoliciesModel[];
+  selectedSubmissionPolicies: SubmissionPoliciesModel[];
   isLoadingSubmissionPolicies: boolean;
 }
 
@@ -27,7 +30,7 @@ export interface OrganizationalUnitStateModel extends CrudStateModel<Organizatio
     list: [],
     current: null,
     queryParameters: new QueryParametersModel(),
-    listSubmissionPolicies: [],
+    selectedSubmissionPolicies: [],
   },
 })
 export class OrganizationalUnitState extends CrudState<OrganizationalUnitsModel> {
@@ -105,34 +108,14 @@ export class OrganizationalUnitState extends CrudState<OrganizationalUnitsModel>
 
   @Action(OrgUnitAction.Update, {cancelUncompleted: true})
   update(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.Update): Observable<OrganizationalUnitsModel> {
-    const oldSubmissionPolicies = _.map(ctx.getState().listSubmissionPolicies, "resId");
-    const newSubmissionPolicies = action.model["submissionPolicies"];
-    //TODO manage subresource as list of items !
-    this.determineSubresourceChange(oldSubmissionPolicies, newSubmissionPolicies);
-
-
-    return super.update(ctx, action);
-    //   .pipe(
-    //   tap(m => {
-    //     ctx.dispatch(CrudActionUtil.get(this.state));
-    //   }),
-    // );
-  }
-
-  determineSubresourceChange(oldSubmissionPolicies, newSubmissionPolicies) {
-    const diff: string[] = _.xor(oldSubmissionPolicies, newSubmissionPolicies);
-    const newResource: string[] = [];
-    const removedResource: string[] = [];
-    diff.forEach(d => {
-      if (_.includes(oldSubmissionPolicies, d)) {
-        removedResource.push(d);
-      } else {
-        newResource.push(d);
-      }
-    });
-
-    console.warn("removed", removedResource);
-    console.warn("created", newResource);
+    return super.update(ctx, action)
+      .pipe(
+        tap(m => {
+          const oldSubmissionPolicies = _.map(ctx.getState().selectedSubmissionPolicies, ModelAttributEnum.resId);
+          const newSubmissionPolicies = action.model["submissionPolicies"];
+          ctx.dispatch(CrudActionUtil.updateSubResource(this.state, ApiResourceNameEnum.SUB_POLICY, action.model.resId, oldSubmissionPolicies, newSubmissionPolicies));
+        }),
+      );
   }
 
   @Action(OrgUnitAction.UpdateSuccess)
@@ -160,26 +143,50 @@ export class OrganizationalUnitState extends CrudState<OrganizationalUnitsModel>
     super.deleteFail(ctx, action);
   }
 
-  @Action(OrgUnitAction.GetAllSubmissionPolicy, {cancelUncompleted: true})
-  getAllSubmissionPolicy(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.GetAllSubmissionPolicy): Observable<CollectionTypedModel<SubmissionPoliciesModel>> {
+  @Action(OrgUnitAction.UpdateSubResourceSubmissionPolicies, {cancelUncompleted: true})
+  updateSubmissionPolicy(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.UpdateSubResourceSubmissionPolicies): void {
+    ctx.patchState({
+      isLoadingSubmissionPolicies: true,
+    });
+    super.updateSubResource(ctx, action, ApiResourceNameEnum.SUB_POLICY, action.parentId);
+  }
+
+  @Action(OrgUnitAction.GetAllSubResourceSubmissionPolicies, {cancelUncompleted: true})
+  getAllSubmissionPolicy(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.GetAllSubResourceSubmissionPolicies): Observable<CollectionTypedModel<SubmissionPoliciesModel>> {
     ctx.patchState({
       isLoadingSubmissionPolicies: true,
     });
     return super.getAllSubResource<SubmissionPoliciesModel>(ctx, action, ApiResourceNameEnum.SUB_POLICY, action.parentId);
   }
 
-  // @Action(OrgUnit.GetAllSubmissionPolicySuccess)
-  // getAllSubmissionPolicySuccess(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnit.GetAllSubmissionPolicySuccess): void {
-  //   ctx.patchState({
-  //     listSubmissionPolicies: action.list._data,
-  //     isLoadingSubmissionPolicies: false,
-  //   });
-  // }
-  //
-  // @Action(OrgUnit.GetAllSubmissionPolicyFail)
-  // getAllSubmissionPolicyFail(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnit.GetAllSubmissionPolicyFail): void {
-  //   ctx.patchState({
-  //     isLoadingSubmissionPolicies: false,
-  //   });
-  // }
+  @Action(OrgUnitAction.GetAllSubResourceSubmissionPoliciesSuccess)
+  getAllSubmissionPolicySuccess(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.GetAllSubResourceSubmissionPoliciesSuccess): void {
+    ctx.patchState({
+      selectedSubmissionPolicies: action.list._data,
+      isLoadingSubmissionPolicies: false,
+    });
+  }
+
+  @Action(OrgUnitAction.GetAllSubResourceSubmissionPoliciesFail)
+  getAllSubmissionPolicyFail(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.GetAllSubResourceSubmissionPoliciesFail): void {
+    ctx.patchState({
+      isLoadingSubmissionPolicies: false,
+    });
+  }
+
+  @Action(OrgUnitAction.CreateSubResourceSubmissionPolicies, {cancelUncompleted: true})
+  createSubmissionPolicy(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.CreateSubResourceSubmissionPolicies): Observable<string[]> {
+    ctx.patchState({
+      isLoadingSubmissionPolicies: true,
+    });
+    return super.createSubResource(ctx, action, ApiResourceNameEnum.SUB_POLICY, action.parentId);
+  }
+
+  @Action(OrgUnitAction.DeleteSubResourceSubmissionPolicies, {cancelUncompleted: true})
+  deleteSubmissionPolicy(ctx: StateContext<OrganizationalUnitStateModel>, action: OrgUnitAction.DeleteSubResourceSubmissionPolicies): Observable<string[]> {
+    ctx.patchState({
+      isLoadingSubmissionPolicies: true,
+    });
+    return super.deleteSubResource(ctx, action, ApiResourceNameEnum.SUB_POLICY, action.parentId);
+  }
 }
diff --git a/src/app/shared/services/api.service.ts b/src/app/shared/services/api.service.ts
index 9e99f75a336f43f2c369fca7c4a1d4ae95b53101..933958c065c9fac84ef4bb37c346b7c20c16c097 100644
--- a/src/app/shared/services/api.service.ts
+++ b/src/app/shared/services/api.service.ts
@@ -168,49 +168,23 @@ export class ApiService {
     );
   }
 
-  // public getSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, queryParameters: QueryParametersModel, customParameters?: { [key: string]: string; }, observe?: "body", reportProgress?: boolean): Observable<CollectionTypedModel<T>>;
-  // public getSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, queryParameters: QueryParametersModel, customParameters?: { [key: string]: string; }, observe?: "response", reportProgress?: boolean): Observable<HttpResponse<CollectionTypedModel<T>>>;
-  // public getSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, queryParameters: QueryParametersModel, customParameters?: { [key: string]: string; }, observe?: "events", reportProgress?: boolean): Observable<HttpEvent<CollectionTypedModel<T>>>;
-  // public getSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, queryParameters?: QueryParametersModel, customParameters?: { [key: string]: string; }, observe: any = "body", reportProgress: boolean = false): Observable<any> {
-  //   const pathEvaluated = this.evaluatePathParentId(subResource, parentId);
-  //   return this.get<T>(pathEvaluated as string, queryParameters, customParameters, observe, reportProgress);
-  // }
-  //
-  // public getSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe?: "body", reportProgress?: boolean): Observable<T>;
-  // public getSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe?: "response", reportProgress?: boolean): Observable<HttpResponse<T>>;
-  // public getSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe?: "events", reportProgress?: boolean): Observable<HttpEvent<T>>;
-  // public getSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe: any = "body", reportProgress: boolean = false): Observable<any> {
-  //   const pathEvaluated = this.evaluatePathParentId(subResource, parentId);
-  //   return this.getById<T>(pathEvaluated as string, resId, observe, reportProgress);
-  // }
-  //
-  // public deleteSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe?: "body", reportProgress?: boolean): Observable<T>;
-  // public deleteSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe?: "response", reportProgress?: boolean): Observable<HttpResponse<T>>;
-  // public deleteSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe?: "events", reportProgress?: boolean): Observable<HttpEvent<T>>;
-  // public deleteSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, observe: any = "body", reportProgress: boolean = false): Observable<any> {
-  //   const pathEvaluated = this.evaluatePathParentId(subResource, parentId);
-  //   return this.deleteById<T>(pathEvaluated as string, resId, observe, reportProgress);
-  // }
-  //
-  // public patchSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, body?: T, observe?: "body", reportProgress?: boolean): Observable<T>;
-  // public patchSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, body?: T, observe?: "response", reportProgress?: boolean): Observable<HttpResponse<T>>;
-  // public patchSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, body?: T, observe?: "events", reportProgress?: boolean): Observable<HttpEvent<T>>;
-  // public patchSubResourceById<T>(subResource: ApiResourceNameEnum, parentId: string, resId: string, body?: T, observe: any = "body", reportProgress: boolean = false): Observable<any> {
-  //   const pathEvaluated = this.evaluatePathParentId(subResource, parentId);
-  //   return this.patchById<T>(pathEvaluated as string, resId, body, observe, reportProgress);
-  // }
-  //
-  // public postSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, body?: T, observe?: "body", reportProgress?: boolean): Observable<T>;
-  // public postSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, body?: T, observe?: "response", reportProgress?: boolean): Observable<HttpResponse<T>>;
-  // public postSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, body?: T, observe?: "events", reportProgress?: boolean): Observable<HttpEvent<T>>;
-  // public postSubResource<T>(subResource: ApiResourceNameEnum, parentId: string, body?: T, observe: any = "body", reportProgress: boolean = false): Observable<any> {
-  //   const pathEvaluated = this.evaluatePathParentId(subResource, parentId);
-  //   return this.post<T>(pathEvaluated as string, body, observe, reportProgress);
-  // }
-  //
-  // private evaluatePathParentId(subResource: ApiResourceNameEnum, parentId: string): string {
-  //   return StringUtil.formatKeyValue(subResource, new KeyValueModel(ApiKeyword.PARENT_ID, parentId));
-  // }
+  public delete<T>(path: string, body?: T, observe?: "body", reportProgress?: boolean): Observable<T>;
+  public delete<T>(path: string, body?: T, observe?: "response", reportProgress?: boolean): Observable<HttpResponse<T>>;
+  public delete<T>(path: string, body?: T, observe?: "events", reportProgress?: boolean): Observable<HttpEvent<T>>;
+  public delete<T>(path: string, body?: T, observe: any = "body", reportProgress: boolean = false): Observable<any> {
+    let headers = this.getHeaders();
+    headers = this.addContentType(headers);
+
+    return this.httpClient.delete<T>(`${this.configuration.basePath}/${path}`,
+      {
+        withCredentials: this.configuration.withCredentials,
+        headers,
+        observe,
+        reportProgress,
+        body,
+      } as any,
+    );
+  }
 
   private getQueryParameters(queryParameters: QueryParametersModel, customParameters: { [p: string]: string }) {
     let queryParametersHttp = new HttpParams({encoder: new CustomHttpUrlEncodingCodec()});
diff --git a/src/app/shared/utils/crud-action.util.ts b/src/app/shared/utils/crud-action.util.ts
index e818084527853bd8f69c3112b4b42b2cf47069b4..df2d061431ba929d15215ba8804aa330fb4b6c1a 100644
--- a/src/app/shared/utils/crud-action.util.ts
+++ b/src/app/shared/utils/crud-action.util.ts
@@ -1,5 +1,6 @@
 import {DepositAction} from "@app/deposit/deposit.action";
 import {CrudAction} from "@app/shared/crud.action";
+import {ApiResourceNameEnum} from "@app/shared/enums/api-resource-name.enum";
 import {StateEnum} from "@app/shared/enums/state.enum";
 import {LanguageAction} from "@app/shared/language.action";
 import {LicenseAction} from "@app/shared/license.action";
@@ -43,10 +44,12 @@ export class CrudActionUtil {
     try {
       return new (namespace)[className](...param);
     } catch (e) {
-      throw Error(`Unable to instance ${state}Action.${className}.`);
+      throw Error(`Unable to instance ${state}Action.${className}. If it's a sub resource, please check that the name of the action is similar to name present in ApiResourceName (converted in PascalCase)`);
     }
   }
 
+  // TODO Find a way to not redeclare parameters (risk of mistake). If this methods go to CrudAction we get circular dependancy because of action namespace use (see getNamespace)
+
   static changeQueryParameters(state: StateEnum, queryParameters: QueryParametersModel): CrudAction.ChangeQueryParameters {
     return CrudActionUtil.getInstanceInternal(state, CrudAction.ChangeQueryParameters.className, queryParameters);
   }
@@ -111,21 +114,55 @@ export class CrudActionUtil {
     return CrudActionUtil.getInstanceInternal(state, CrudAction.DeleteFail.className);
   }
 
-  // static getAllSubresourceSuccess<T>(state: StateEnum, urlSubresource: SubResourceApiEnum, list: CollectionTypedModel<T>): GetAllSubresourceSuccess<any> {
-  // return CrudActionUtil.getInstanceInternal(state, CrudAction.GetAllSubresourceSuccess.className);
-  //   if (state === StateEnum.organizationalUnit) {
-  //     if (urlSubresource === AdminSubResourceApiEnum.organizationalUnitsSubmissionPolicy) {
-  //       return new OrgUnitGetAllSubmissionPolicySuccess(list);
-  //     }
-  //   }
-  // }
-  //
-  // static getAllSubresourceFail(state: StateEnum, urlSubresource: SubResourceApiEnum): GetAllSubresourceFail {
-  // return CrudActionUtil.getInstanceInternal(state, CrudAction.GetAllSubresourceFail.className);
-  //   if (state === StateEnum.organizationalUnit) {
-  //     if (urlSubresource === AdminSubResourceApiEnum.organizationalUnitsSubmissionPolicy) {
-  //       return new OrgUnitGetAllSubmissionPolicyFail();
-  //     }
-  //   }
-  // }
+  static getAllSubResource(state: StateEnum, subResource: ApiResourceNameEnum, parentId: string, queryParameters?: QueryParametersModel): CrudAction.GetAllSubResource {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.GetAllSubResource.className, CrudActionUtil.formatSubResourceName(subResource)), parentId, queryParameters);
+  }
+
+  static getAllSubResourceSuccess<T>(state: StateEnum, subResource: ApiResourceNameEnum, list: CollectionTypedModel<T>): CrudAction.GetAllSubResourceSuccess<any> {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.GetAllSubResourceSuccess.className, CrudActionUtil.formatSubResourceName(subResource)), list);
+  }
+
+  static getAllSubResourceFail(state: StateEnum, subResource: ApiResourceNameEnum): CrudAction.GetAllSubResourceFail {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.GetAllSubResourceFail.className, CrudActionUtil.formatSubResourceName(subResource)), subResource);
+  }
+
+  static createSubResource(state: StateEnum, subResource: ApiResourceNameEnum, parentId: string, listResId: string[]): CrudAction.CreateSubResource {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.CreateSubResource.className, CrudActionUtil.formatSubResourceName(subResource)), parentId, listResId);
+  }
+
+  static createSubResourceSuccess(state: StateEnum, subResource: ApiResourceNameEnum): CrudAction.CreateSubResourceSuccess {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.CreateSubResourceSuccess.className, CrudActionUtil.formatSubResourceName(subResource)));
+  }
+
+  static createSubResourceFail(state: StateEnum, subResource: ApiResourceNameEnum): CrudAction.CreateSubResourceFail {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.CreateSubResourceFail.className, CrudActionUtil.formatSubResourceName(subResource)), subResource);
+  }
+
+  static deleteSubResource(state: StateEnum, subResource: ApiResourceNameEnum, parentId: string, listResId: string[]): CrudAction.DeleteSubResource {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.DeleteSubResource.className, CrudActionUtil.formatSubResourceName(subResource)), parentId, listResId);
+  }
+
+  static deleteSubResourceSuccess(state: StateEnum, subResource: ApiResourceNameEnum): CrudAction.DeleteSubResourceSuccess {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.DeleteSubResourceSuccess.className, CrudActionUtil.formatSubResourceName(subResource)));
+  }
+
+  static deleteSubResourceFail(state: StateEnum, subResource: ApiResourceNameEnum): CrudAction.DeleteSubResourceFail {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.DeleteSubResourceFail.className, CrudActionUtil.formatSubResourceName(subResource)), subResource);
+  }
+
+  static updateSubResource(state: StateEnum, subResource: ApiResourceNameEnum, parentId: string, oldResId: string[], newResId: string[]): CrudAction.DeleteSubResource {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.UpdateSubResource.className, CrudActionUtil.formatSubResourceName(subResource)), parentId, oldResId, newResId);
+  }
+
+  static updateSubResourceSuccess(state: StateEnum, subResource: ApiResourceNameEnum): CrudAction.DeleteSubResourceSuccess {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.UpdateSubResourceSuccess.className, CrudActionUtil.formatSubResourceName(subResource)));
+  }
+
+  static updateSubResourceFail(state: StateEnum, subResource: ApiResourceNameEnum): CrudAction.DeleteSubResourceFail {
+    return CrudActionUtil.getInstanceInternal(state, StringUtil.format(CrudAction.UpdateSubResourceFail.className, CrudActionUtil.formatSubResourceName(subResource)), subResource);
+  }
+
+  private static formatSubResourceName(subResource: ApiResourceNameEnum): string {
+    return StringUtil.convertSpinalCaseToPascalCase(subResource as string);
+  }
 }
diff --git a/src/app/shared/utils/string.util.ts b/src/app/shared/utils/string.util.ts
index a4160b0dd4b766987f27448643b84f6db3baffc3..cff43961e563b50aba46ea9a6e1cb52c3959a5fd 100644
--- a/src/app/shared/utils/string.util.ts
+++ b/src/app/shared/utils/string.util.ts
@@ -1,4 +1,5 @@
 import {KeyValueModel} from "@app/shared/models/key-value.model";
+import * as changeCase from "change-case";
 
 export class StringUtil {
   static readonly stringEmpty = "";
@@ -16,4 +17,14 @@ export class StringUtil {
     });
     return str;
   }
+
+  static convertSpinalCaseToPascalCase(origin: string): string {
+    origin = origin.replace("-", " ");
+    return changeCase.pascalCase(origin);
+  }
+
+  static convertSpinalCaseToCamelCase(origin: string): string {
+    origin = origin.replace("-", " ");
+    return changeCase.camelCase(origin);
+  }
 }
diff --git a/src/app/shared/views/abstract-detail/abstract-detail.view.ts b/src/app/shared/views/abstract-detail/abstract-detail.view.ts
index e89102efebc357a0a87c8859acd8dfef9d392545..862190e987675a89f4a59f256a75596956bcdcc1 100644
--- a/src/app/shared/views/abstract-detail/abstract-detail.view.ts
+++ b/src/app/shared/views/abstract-detail/abstract-detail.view.ts
@@ -6,6 +6,7 @@ import {CrudAction} from "@app/shared/crud.action";
 import {CrudStateModel} from "@app/shared/crud.state";
 import {AbstractDeleteDialog} from "@app/shared/dialogs/abstract-delete/abstract-delete.dialog";
 import {BaseDirective} from "@app/shared/directives/base.directive";
+import {ModelAttributEnum} from "@app/shared/enums/model-attribut.enum";
 import {StateEnum} from "@app/shared/enums/state.enum";
 import {DeleteDialogModel} from "@app/shared/models/delete-dialog.model";
 import {CrudActionUtil} from "@app/shared/utils/crud-action.util";
@@ -60,7 +61,7 @@ export abstract class AbstractDetailView<T, U extends CrudStateModel<T>> extends
     const datas = {} as DeleteDialogModel;
     this.addToSubscription(this.current$.pipe(take(1)).subscribe((model: T) => {
       datas.name = model[this.KEY_PARAM_NAME];
-      datas.resId = model["resId"];
+      datas.resId = model[ModelAttributEnum.resId];
     }));
     const dialogRef = this.dialog.open(CrudDialogUtil.delete(this.state) as ComponentType<AbstractDeleteDialog<T, U>>, {
       width: "250px",
diff --git a/src/app/shared/views/abstract-list/abstract-list.view.ts b/src/app/shared/views/abstract-list/abstract-list.view.ts
index 714c9f9883ac6063fe0b8dfc642f432091be9086..2e56c4b0f32ace904723078c9cc56d9a6baa7635 100644
--- a/src/app/shared/views/abstract-list/abstract-list.view.ts
+++ b/src/app/shared/views/abstract-list/abstract-list.view.ts
@@ -1,6 +1,7 @@
 import {OnInit} from "@angular/core";
 import {CrudStateModel} from "@app/shared/crud.state";
 import {BaseDirective} from "@app/shared/directives/base.directive";
+import {ModelAttributEnum} from "@app/shared/enums/model-attribut.enum";
 import {StateEnum} from "@app/shared/enums/state.enum";
 import {DataTableColumnsModel} from "@app/shared/models/data-table-columns.model";
 import {QueryParametersModel} from "@app/shared/models/query-parameters.model";
@@ -44,7 +45,7 @@ export abstract class AbstractListView<T, U extends CrudStateModel<T>> extends B
   }
 
   showDetail(model: T) {
-    this.store.dispatch(new Navigate([CrudRouteUtil.getDetailRoute(this.state), model["resId"]]));
+    this.store.dispatch(new Navigate([CrudRouteUtil.getDetailRoute(this.state), model[ModelAttributEnum.resId]]));
   }
 
   onQueryParametersEvent($event: QueryParametersModel) {