diff --git a/ema/urls.py b/ema/urls.py
index 63073d6e..92877271 100644
--- a/ema/urls.py
+++ b/ema/urls.py
@@ -6,7 +6,17 @@ Created on: 19.08.21
 
 """
 from django.urls import path
-from ema.views import *
+
+from ema.views.action import action_new_view, action_edit_view, action_remove_view
+from ema.views.deadline import deadline_new_view, deadline_edit_view, deadline_remove_view
+from ema.views.document import document_new_view, get_document_view, remove_document_view, edit_document_view
+from ema.views.ema import index_view, new_view, new_id_view, detail_view, edit_view, remove_view
+from ema.views.log import log_view
+from ema.views.record import record_view
+from ema.views.report import report_view
+from ema.views.resubmission import create_resubmission_view
+from ema.views.share import share_view, create_share_view
+from ema.views.state import state_new_view, state_remove_view, state_edit_view
 
 app_name = "ema"
 urlpatterns = [
diff --git a/ema/views.py b/ema/views.py
deleted file mode 100644
index 2dd6e51f..00000000
--- a/ema/views.py
+++ /dev/null
@@ -1,739 +0,0 @@
-from django.contrib import messages
-from django.contrib.auth.decorators import login_required
-from django.db.models import Sum
-from django.http import HttpRequest, JsonResponse
-from django.shortcuts import render, get_object_or_404, redirect
-from django.urls import reverse
-from django.utils.translation import gettext_lazy as _
-
-from compensation.forms.modals.compensation_action import NewCompensationActionModalForm, \
-    EditCompensationActionModalForm, RemoveCompensationActionModalForm
-from compensation.forms.modals.deadline import NewDeadlineModalForm, EditDeadlineModalForm
-from compensation.forms.modals.state import NewCompensationStateModalForm, RemoveCompensationStateModalForm, \
-    EditCompensationStateModalForm
-from compensation.models import CompensationAction, CompensationState
-from ema.forms import NewEmaForm, EditEmaForm, NewEmaDocumentModalForm
-from ema.tables import EmaTable
-from intervention.forms.modals.share import ShareModalForm
-from konova.contexts import BaseContext
-from konova.decorators import conservation_office_group_required, shared_access_required
-from ema.models import Ema, EmaDocument
-from konova.forms.modals import RemoveModalForm, RecordModalForm, RemoveDeadlineModalForm, \
-    EditDocumentModalForm, ResubmissionModalForm
-from konova.forms import SimpleGeomForm
-from konova.models import Deadline
-from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
-from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
-from konova.utils.documents import get_document, remove_document
-from konova.utils.generators import generate_qr_code
-from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION, \
-    DOCUMENT_ADDED, COMPENSATION_STATE_REMOVED, COMPENSATION_STATE_ADDED, COMPENSATION_ACTION_REMOVED, \
-    COMPENSATION_ACTION_ADDED, DEADLINE_ADDED, DEADLINE_REMOVED, DOCUMENT_EDITED, COMPENSATION_STATE_EDITED, \
-    COMPENSATION_ACTION_EDITED, DEADLINE_EDITED, RECORDED_BLOCKS_EDIT
-from konova.utils.user_checks import in_group
-
-
-@login_required
-def index_view(request: HttpRequest):
-    """ Renders the index view for EMAs
-
-    Args:
-        request (HttpRequest): The incoming request
-
-    Returns:
-
-    """
-    template = "generic_index.html"
-    emas = Ema.objects.filter(
-        deleted=None,
-    ).order_by(
-        "-modified"
-    )
-    table = EmaTable(
-        request,
-        queryset=emas
-    )
-    context = {
-        "table": table,
-        TAB_TITLE_IDENTIFIER: _("EMAs - Overview"),
-    }
-    context = BaseContext(request, context).context
-    return render(request, template, context)
-
-
-@login_required
-@conservation_office_group_required
-def new_view(request: HttpRequest):
-    """
-    Renders a view for a new eco account creation
-
-    Args:
-        request (HttpRequest): The incoming request
-
-    Returns:
-
-    """
-    template = "ema/form/view.html"
-    data_form = NewEmaForm(request.POST or None)
-    geom_form = SimpleGeomForm(request.POST or None, read_only=False)
-    if request.method == "POST":
-        if data_form.is_valid() and geom_form.is_valid():
-            generated_identifier = data_form.cleaned_data.get("identifier", None)
-            ema = data_form.save(request.user, geom_form)
-            if generated_identifier != ema.identifier:
-                messages.info(
-                    request,
-                    IDENTIFIER_REPLACED.format(
-                        generated_identifier,
-                        ema.identifier
-                    )
-                )
-            messages.success(request, _("EMA {} added").format(ema.identifier))
-            return redirect("ema:detail", id=ema.id)
-        else:
-            messages.error(request, FORM_INVALID, extra_tags="danger",)
-    else:
-        # For clarification: nothing in this case
-        pass
-    context = {
-        "form": data_form,
-        "geom_form": geom_form,
-        TAB_TITLE_IDENTIFIER: _("New EMA"),
-    }
-    context = BaseContext(request, context).context
-    return render(request, template, context)
-
-
-@login_required
-@conservation_office_group_required
-def new_id_view(request: HttpRequest):
-    """ JSON endpoint
-
-    Provides fetching of free identifiers for e.g. AJAX calls
-
-    """
-    tmp = Ema()
-    identifier = tmp.generate_new_identifier()
-    while Ema.objects.filter(identifier=identifier).exists():
-        identifier = tmp.generate_new_identifier()
-    return JsonResponse(
-        data={
-            "gen_data": identifier
-        }
-    )
-
-
-@login_required
-def detail_view(request: HttpRequest, id: str):
-    """ Renders the detail view of an EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA id
-
-    Returns:
-
-    """
-    template = "ema/detail/view.html"
-    ema = get_object_or_404(Ema, id=id, deleted=None)
-
-    geom_form = SimpleGeomForm(instance=ema)
-    parcels = ema.get_underlying_parcels()
-    _user = request.user
-    is_data_shared = ema.is_shared_with(_user)
-
-    # Order states according to surface
-    before_states = ema.before_states.all().order_by("-surface")
-    after_states = ema.after_states.all().order_by("-surface")
-
-    # Precalculate logical errors between before- and after-states
-    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
-    sum_before_states = before_states.aggregate(Sum("surface"))["surface__sum"] or 0
-    sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
-    diff_states = abs(sum_before_states - sum_after_states)
-
-    ema.set_status_messages(request)
-
-    context = {
-        "obj": ema,
-        "geom_form": geom_form,
-        "parcels": parcels,
-        "has_access": is_data_shared,
-        "before_states": before_states,
-        "after_states": after_states,
-        "sum_before_states": sum_before_states,
-        "sum_after_states": sum_after_states,
-        "diff_states": diff_states,
-        "is_default_member": in_group(_user, DEFAULT_GROUP),
-        "is_zb_member": in_group(_user, ZB_GROUP),
-        "is_ets_member": in_group(_user, ETS_GROUP),
-        "LANIS_LINK": ema.get_LANIS_link(),
-        TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}",
-        "has_finished_deadlines": ema.get_finished_deadlines().exists(),
-    }
-    context = BaseContext(request, context).context
-    return render(request, template, context)
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def log_view(request: HttpRequest, id: str):
-    """ Renders a log view using modal
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    template = "modal/modal_generic.html"
-    body_template = "log.html"
-
-    context = {
-        "modal_body_template": body_template,
-        "log": ema.log.all(),
-        "modal_title": _("Log"),
-    }
-    context = BaseContext(request, context).context
-    return render(request, template, context)
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def edit_view(request: HttpRequest, id: str):
-    """
-    Renders a view for editing compensations
-
-    Args:
-        request (HttpRequest): The incoming request
-
-    Returns:
-
-    """
-    template = "compensation/form/view.html"
-    # Get object from db
-    ema = get_object_or_404(Ema, id=id)
-    if ema.is_recorded:
-        messages.info(
-            request,
-            RECORDED_BLOCKS_EDIT
-        )
-        return redirect("ema:detail", id=id)
-
-    # Create forms, initialize with values from db/from POST request
-    data_form = EditEmaForm(request.POST or None, instance=ema)
-    geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=ema)
-    if request.method == "POST":
-        if data_form.is_valid() and geom_form.is_valid():
-            # The data form takes the geom form for processing, as well as the performing user
-            ema = data_form.save(request.user, geom_form)
-            messages.success(request, _("EMA {} edited").format(ema.identifier))
-            return redirect("ema:detail", id=ema.id)
-        else:
-            messages.error(request, FORM_INVALID, extra_tags="danger",)
-    else:
-        # For clarification: nothing in this case
-        pass
-    context = {
-        "form": data_form,
-        "geom_form": geom_form,
-        TAB_TITLE_IDENTIFIER: _("Edit {}").format(ema.identifier),
-    }
-    context = BaseContext(request, context).context
-    return render(request, template, context)
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def remove_view(request: HttpRequest, id: str):
-    """ Renders a modal view for removing the EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    form = RemoveModalForm(request.POST or None, instance=ema, request=request)
-    return form.process_request(
-        request=request,
-        msg_success=_("EMA removed"),
-        redirect_url=reverse("ema:index"),
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def record_view(request: HttpRequest, id: str):
-    """ Renders a modal view for recording the EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    msg_succ = _("{} unrecorded") if ema.recorded else _("{} recorded")
-    form = RecordModalForm(request.POST or None, instance=ema, request=request)
-    return form.process_request(
-        request=request,
-        msg_success=msg_succ.format("EMA"),
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def state_new_view(request: HttpRequest, id: str):
-    """ Renders a form for adding new states for an EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id to which the new state will be related
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    form = NewCompensationStateModalForm(request.POST or None, instance=ema, request=request)
-    return form.process_request(
-        request,
-        msg_success=COMPENSATION_STATE_ADDED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def action_new_view(request: HttpRequest, id: str):
-    """ Renders a form for adding new actions for an EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id to which the new state will be related
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    form = NewCompensationActionModalForm(request.POST or None, instance=ema, request=request)
-    return form.process_request(
-        request,
-        msg_success=COMPENSATION_ACTION_ADDED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def action_edit_view(request: HttpRequest, id: str, action_id: str):
-    """ Renders a form for editing an actions for an EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id
-        action_id (str): The action id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    action = get_object_or_404(CompensationAction, id=action_id)
-    form = EditCompensationActionModalForm(request.POST or None, instance=ema, action=action, request=request)
-    return form.process_request(
-        request,
-        msg_success=COMPENSATION_ACTION_EDITED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def deadline_new_view(request: HttpRequest, id: str):
-    """ Renders a form for adding new states for an EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id to which the new state will be related
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    form = NewDeadlineModalForm(request.POST or None, instance=ema, request=request)
-    return form.process_request(
-        request,
-        msg_success=DEADLINE_ADDED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def document_new_view(request: HttpRequest, id: str):
-    """ Renders a form for uploading new documents
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA's id to which the new document will be related
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    form = NewEmaDocumentModalForm(request.POST or None, request.FILES or None, instance=ema, request=request)
-    return form.process_request(
-        request,
-        msg_success=DOCUMENT_ADDED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def get_document_view(request: HttpRequest, id: str, doc_id: str):
-    """ Returns the document as downloadable file
-
-    Wraps the generic document fetcher function from konova.utils.
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA id
-        doc_id (str): The document id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    doc = get_object_or_404(EmaDocument, id=doc_id)
-    return get_document(doc)
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def edit_document_view(request: HttpRequest, id: str, doc_id: str):
-    """ Removes the document from the database and file system
-
-    Wraps the generic functionality from konova.utils.
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA id
-        doc_id (str): The document id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    doc = get_object_or_404(EmaDocument, id=doc_id)
-    form = EditDocumentModalForm(request.POST or None, request.FILES or None, instance=ema, document=doc, request=request)
-    return form.process_request(
-        request,
-        DOCUMENT_EDITED,
-        reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def remove_document_view(request: HttpRequest, id:str, doc_id: str):
-    """ Removes the document from the database and file system
-
-    Wraps the generic functionality from konova.utils.
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The EMA id
-        doc_id (str): The document id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    doc = get_object_or_404(EmaDocument, id=doc_id)
-    return remove_document(
-        request,
-        doc
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def state_remove_view(request: HttpRequest, id: str, state_id: str):
-    """ Renders a form for removing an EMA state
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The ema id
-        state_id (str): The state's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    state = get_object_or_404(CompensationState, id=state_id)
-    form = RemoveCompensationStateModalForm(request.POST or None, instance=ema, state=state, request=request)
-    return form.process_request(
-        request,
-        msg_success=COMPENSATION_STATE_REMOVED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def state_edit_view(request: HttpRequest, id: str, state_id: str):
-    """ Renders a form for editing an EMA state
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The ema id
-        state_id (str): The state's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    state = get_object_or_404(CompensationState, id=state_id)
-    form = EditCompensationStateModalForm(request.POST or None, instance=ema, state=state, request=request)
-    return form.process_request(
-        request,
-        msg_success=COMPENSATION_STATE_EDITED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def action_remove_view(request: HttpRequest, id: str, action_id: str):
-    """ Renders a form for removing an EMA action
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The ema id
-        id (str): The action's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    action = get_object_or_404(CompensationAction, id=action_id)
-    form = RemoveCompensationActionModalForm(request.POST or None, instance=ema, action=action, request=request)
-    return form.process_request(
-        request,
-        msg_success=COMPENSATION_ACTION_REMOVED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-def report_view(request:HttpRequest, id: str):
-    """ Renders the public report view
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The id of the intervention
-
-    Returns:
-
-    """
-    # Reuse the compensation report template since EMAs are structurally identical
-    template = "ema/report/report.html"
-    ema = get_object_or_404(Ema, id=id)
-
-    tab_title = _("Report {}").format(ema.identifier)
-    # If intervention is not recorded (yet or currently) we need to render another template without any data
-    if not ema.is_ready_for_publish():
-        template = "report/unavailable.html"
-        context = {
-            TAB_TITLE_IDENTIFIER: tab_title,
-        }
-        context = BaseContext(request, context).context
-        return render(request, template, context)
-
-    # Prepare data for map viewer
-    geom_form = SimpleGeomForm(
-        instance=ema,
-    )
-    parcels = ema.get_underlying_parcels()
-
-    qrcode_url = request.build_absolute_uri(reverse("ema:report", args=(id,)))
-    qrcode_img = generate_qr_code(qrcode_url, 10)
-    qrcode_lanis_url = ema.get_LANIS_link()
-    qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
-
-    # Order states by surface
-    before_states = ema.before_states.all().order_by("-surface").prefetch_related("biotope_type")
-    after_states = ema.after_states.all().order_by("-surface").prefetch_related("biotope_type")
-    actions = ema.actions.all().prefetch_related("action_type")
-
-    context = {
-        "obj": ema,
-        "qrcode": {
-            "img": qrcode_img,
-            "url": qrcode_url
-        },
-        "qrcode_lanis": {
-            "img": qrcode_img_lanis,
-            "url": qrcode_lanis_url
-        },
-        "has_access": False,  # disables action buttons during rendering
-        "before_states": before_states,
-        "after_states": after_states,
-        "geom_form": geom_form,
-        "parcels": parcels,
-        "actions": actions,
-        TAB_TITLE_IDENTIFIER: tab_title,
-    }
-    context = BaseContext(request, context).context
-    return render(request, template, context)
-
-
-@login_required
-def share_view(request: HttpRequest, id: str, token: str):
-    """ Performs sharing of an ema
-
-    If token given in url is not valid, the user will be redirected to the dashboard
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): EMA's id
-        token (str): Access token for EMA
-
-    Returns:
-
-    """
-    user = request.user
-    obj = get_object_or_404(Ema, id=id)
-    # Check tokens
-    if obj.access_token == token:
-        # Send different messages in case user has already been added to list of sharing users
-        if obj.is_shared_with(user):
-            messages.info(
-                request,
-                _("{} has already been shared with you").format(obj.identifier)
-            )
-        else:
-            messages.success(
-                request,
-                _("{} has been shared with you").format(obj.identifier)
-            )
-            obj.share_with_user(user)
-        return redirect("ema:detail", id=id)
-    else:
-        messages.error(
-            request,
-            _("Share link invalid"),
-            extra_tags="danger",
-        )
-        return redirect("home")
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def create_share_view(request: HttpRequest, id: str):
-    """ Renders sharing form for an Ema
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): Ema's id
-
-    Returns:
-
-    """
-    obj = get_object_or_404(Ema, id=id)
-    form = ShareModalForm(request.POST or None, instance=obj, request=request)
-    return form.process_request(
-        request,
-        msg_success=_("Share settings updated")
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def deadline_edit_view(request: HttpRequest, id: str, deadline_id: str):
-    """ Renders a form for editing deadlines from a compensation
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The compensation's id
-        deadline_id (str): The deadline's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    deadline = get_object_or_404(Deadline, id=deadline_id)
-    form = EditDeadlineModalForm(request.POST or None, instance=ema, deadline=deadline, request=request)
-    return form.process_request(
-        request,
-        msg_success=DEADLINE_EDITED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def deadline_remove_view(request: HttpRequest, id: str, deadline_id: str):
-    """ Renders a form for removing deadlines from a compensation
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): The compensation's id
-        deadline_id (str): The deadline's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    deadline = get_object_or_404(Deadline, id=deadline_id)
-    form = RemoveDeadlineModalForm(request.POST or None, instance=ema, deadline=deadline, request=request)
-    return form.process_request(
-        request,
-        msg_success=DEADLINE_REMOVED,
-        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
-    )
-
-
-@login_required
-@conservation_office_group_required
-@shared_access_required(Ema, "id")
-def create_resubmission_view(request: HttpRequest, id: str):
-    """ Renders resubmission form for an EMA
-
-    Args:
-        request (HttpRequest): The incoming request
-        id (str): EMA's id
-
-    Returns:
-
-    """
-    ema = get_object_or_404(Ema, id=id)
-    form = ResubmissionModalForm(request.POST or None, instance=ema, request=request)
-    form.action_url = reverse("ema:resubmission-create", args=(id,))
-    return form.process_request(
-        request,
-        msg_success=_("Resubmission set"),
-        redirect_url=reverse("ema:detail", args=(id,))
-    )
diff --git a/ema/views/__init__.py b/ema/views/__init__.py
new file mode 100644
index 00000000..3a996e1f
--- /dev/null
+++ b/ema/views/__init__.py
@@ -0,0 +1,7 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
diff --git a/ema/views/action.py b/ema/views/action.py
new file mode 100644
index 00000000..bd13646c
--- /dev/null
+++ b/ema/views/action.py
@@ -0,0 +1,89 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404
+from django.urls import reverse
+
+from compensation.forms.modals.compensation_action import RemoveCompensationActionModalForm, \
+    EditCompensationActionModalForm, NewCompensationActionModalForm
+from compensation.models import CompensationAction
+from ema.models import Ema
+from konova.decorators import shared_access_required, conservation_office_group_required
+from konova.utils.message_templates import COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_EDITED, \
+    COMPENSATION_ACTION_ADDED
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def action_new_view(request: HttpRequest, id: str):
+    """ Renders a form for adding new actions for an EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id to which the new state will be related
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    form = NewCompensationActionModalForm(request.POST or None, instance=ema, request=request)
+    return form.process_request(
+        request,
+        msg_success=COMPENSATION_ACTION_ADDED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def action_edit_view(request: HttpRequest, id: str, action_id: str):
+    """ Renders a form for editing an actions for an EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id
+        action_id (str): The action id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    action = get_object_or_404(CompensationAction, id=action_id)
+    form = EditCompensationActionModalForm(request.POST or None, instance=ema, action=action, request=request)
+    return form.process_request(
+        request,
+        msg_success=COMPENSATION_ACTION_EDITED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def action_remove_view(request: HttpRequest, id: str, action_id: str):
+    """ Renders a form for removing an EMA action
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The ema id
+        id (str): The action's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    action = get_object_or_404(CompensationAction, id=action_id)
+    form = RemoveCompensationActionModalForm(request.POST or None, instance=ema, action=action, request=request)
+    return form.process_request(
+        request,
+        msg_success=COMPENSATION_ACTION_REMOVED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
diff --git a/ema/views/deadline.py b/ema/views/deadline.py
new file mode 100644
index 00000000..223ceeb0
--- /dev/null
+++ b/ema/views/deadline.py
@@ -0,0 +1,90 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404
+from django.urls import reverse
+
+from compensation.forms.modals.deadline import EditDeadlineModalForm, NewDeadlineModalForm
+from ema.models import Ema
+from konova.decorators import shared_access_required, conservation_office_group_required
+from konova.forms.modals import RemoveDeadlineModalForm
+from konova.models import Deadline
+from konova.utils.message_templates import DEADLINE_REMOVED, DEADLINE_EDITED, DEADLINE_ADDED
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def deadline_new_view(request: HttpRequest, id: str):
+    """ Renders a form for adding new states for an EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id to which the new state will be related
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    form = NewDeadlineModalForm(request.POST or None, instance=ema, request=request)
+    return form.process_request(
+        request,
+        msg_success=DEADLINE_ADDED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def deadline_edit_view(request: HttpRequest, id: str, deadline_id: str):
+    """ Renders a form for editing deadlines from a compensation
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The compensation's id
+        deadline_id (str): The deadline's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    deadline = get_object_or_404(Deadline, id=deadline_id)
+    form = EditDeadlineModalForm(request.POST or None, instance=ema, deadline=deadline, request=request)
+    return form.process_request(
+        request,
+        msg_success=DEADLINE_EDITED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def deadline_remove_view(request: HttpRequest, id: str, deadline_id: str):
+    """ Renders a form for removing deadlines from a compensation
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The compensation's id
+        deadline_id (str): The deadline's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    deadline = get_object_or_404(Deadline, id=deadline_id)
+    form = RemoveDeadlineModalForm(request.POST or None, instance=ema, deadline=deadline, request=request)
+    return form.process_request(
+        request,
+        msg_success=DEADLINE_REMOVED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
diff --git a/ema/views/document.py b/ema/views/document.py
new file mode 100644
index 00000000..faacb5bc
--- /dev/null
+++ b/ema/views/document.py
@@ -0,0 +1,111 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404
+from django.urls import reverse
+
+from ema.forms import NewEmaDocumentModalForm
+from ema.models import Ema, EmaDocument
+from konova.decorators import shared_access_required, conservation_office_group_required
+from konova.forms.modals import EditDocumentModalForm
+from konova.utils.documents import get_document, remove_document
+from konova.utils.message_templates import DOCUMENT_ADDED, DOCUMENT_EDITED
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def document_new_view(request: HttpRequest, id: str):
+    """ Renders a form for uploading new documents
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id to which the new document will be related
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    form = NewEmaDocumentModalForm(request.POST or None, request.FILES or None, instance=ema, request=request)
+    return form.process_request(
+        request,
+        msg_success=DOCUMENT_ADDED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def get_document_view(request: HttpRequest, id: str, doc_id: str):
+    """ Returns the document as downloadable file
+
+    Wraps the generic document fetcher function from konova.utils.
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA id
+        doc_id (str): The document id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    doc = get_object_or_404(EmaDocument, id=doc_id)
+    return get_document(doc)
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def edit_document_view(request: HttpRequest, id: str, doc_id: str):
+    """ Removes the document from the database and file system
+
+    Wraps the generic functionality from konova.utils.
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA id
+        doc_id (str): The document id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    doc = get_object_or_404(EmaDocument, id=doc_id)
+    form = EditDocumentModalForm(request.POST or None, request.FILES or None, instance=ema, document=doc, request=request)
+    return form.process_request(
+        request,
+        DOCUMENT_EDITED,
+        reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def remove_document_view(request: HttpRequest, id:str, doc_id: str):
+    """ Removes the document from the database and file system
+
+    Wraps the generic functionality from konova.utils.
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA id
+        doc_id (str): The document id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    doc = get_object_or_404(EmaDocument, id=doc_id)
+    return remove_document(
+        request,
+        doc
+    )
+
diff --git a/ema/views/ema.py b/ema/views/ema.py
new file mode 100644
index 00000000..f2b4d3b8
--- /dev/null
+++ b/ema/views/ema.py
@@ -0,0 +1,237 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib import messages
+from django.contrib.auth.decorators import login_required
+from django.db.models import Sum
+from django.http import HttpRequest, JsonResponse
+from django.shortcuts import get_object_or_404, redirect, render
+from django.urls import reverse
+from django.utils.translation import gettext_lazy as _
+
+from ema.forms import NewEmaForm, EditEmaForm
+from ema.models import Ema
+from ema.tables import EmaTable
+from konova.contexts import BaseContext
+from konova.decorators import shared_access_required, conservation_office_group_required
+from konova.forms import SimpleGeomForm
+from konova.forms.modals import RemoveModalForm
+from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
+from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
+from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, IDENTIFIER_REPLACED, FORM_INVALID
+from konova.utils.user_checks import in_group
+
+
+@login_required
+def index_view(request: HttpRequest):
+    """ Renders the index view for EMAs
+
+    Args:
+        request (HttpRequest): The incoming request
+
+    Returns:
+
+    """
+    template = "generic_index.html"
+    emas = Ema.objects.filter(
+        deleted=None,
+    ).order_by(
+        "-modified"
+    )
+    table = EmaTable(
+        request,
+        queryset=emas
+    )
+    context = {
+        "table": table,
+        TAB_TITLE_IDENTIFIER: _("EMAs - Overview"),
+    }
+    context = BaseContext(request, context).context
+    return render(request, template, context)
+
+
+@login_required
+@conservation_office_group_required
+def new_view(request: HttpRequest):
+    """
+    Renders a view for a new eco account creation
+
+    Args:
+        request (HttpRequest): The incoming request
+
+    Returns:
+
+    """
+    template = "ema/form/view.html"
+    data_form = NewEmaForm(request.POST or None)
+    geom_form = SimpleGeomForm(request.POST or None, read_only=False)
+    if request.method == "POST":
+        if data_form.is_valid() and geom_form.is_valid():
+            generated_identifier = data_form.cleaned_data.get("identifier", None)
+            ema = data_form.save(request.user, geom_form)
+            if generated_identifier != ema.identifier:
+                messages.info(
+                    request,
+                    IDENTIFIER_REPLACED.format(
+                        generated_identifier,
+                        ema.identifier
+                    )
+                )
+            messages.success(request, _("EMA {} added").format(ema.identifier))
+            return redirect("ema:detail", id=ema.id)
+        else:
+            messages.error(request, FORM_INVALID, extra_tags="danger",)
+    else:
+        # For clarification: nothing in this case
+        pass
+    context = {
+        "form": data_form,
+        "geom_form": geom_form,
+        TAB_TITLE_IDENTIFIER: _("New EMA"),
+    }
+    context = BaseContext(request, context).context
+    return render(request, template, context)
+
+
+@login_required
+@conservation_office_group_required
+def new_id_view(request: HttpRequest):
+    """ JSON endpoint
+
+    Provides fetching of free identifiers for e.g. AJAX calls
+
+    """
+    tmp = Ema()
+    identifier = tmp.generate_new_identifier()
+    while Ema.objects.filter(identifier=identifier).exists():
+        identifier = tmp.generate_new_identifier()
+    return JsonResponse(
+        data={
+            "gen_data": identifier
+        }
+    )
+
+
+@login_required
+def detail_view(request: HttpRequest, id: str):
+    """ Renders the detail view of an EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA id
+
+    Returns:
+
+    """
+    template = "ema/detail/view.html"
+    ema = get_object_or_404(Ema, id=id, deleted=None)
+
+    geom_form = SimpleGeomForm(instance=ema)
+    parcels = ema.get_underlying_parcels()
+    _user = request.user
+    is_data_shared = ema.is_shared_with(_user)
+
+    # Order states according to surface
+    before_states = ema.before_states.all().order_by("-surface")
+    after_states = ema.after_states.all().order_by("-surface")
+
+    # Precalculate logical errors between before- and after-states
+    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
+    sum_before_states = before_states.aggregate(Sum("surface"))["surface__sum"] or 0
+    sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
+    diff_states = abs(sum_before_states - sum_after_states)
+
+    ema.set_status_messages(request)
+
+    context = {
+        "obj": ema,
+        "geom_form": geom_form,
+        "parcels": parcels,
+        "has_access": is_data_shared,
+        "before_states": before_states,
+        "after_states": after_states,
+        "sum_before_states": sum_before_states,
+        "sum_after_states": sum_after_states,
+        "diff_states": diff_states,
+        "is_default_member": in_group(_user, DEFAULT_GROUP),
+        "is_zb_member": in_group(_user, ZB_GROUP),
+        "is_ets_member": in_group(_user, ETS_GROUP),
+        "LANIS_LINK": ema.get_LANIS_link(),
+        TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}",
+        "has_finished_deadlines": ema.get_finished_deadlines().exists(),
+    }
+    context = BaseContext(request, context).context
+    return render(request, template, context)
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def edit_view(request: HttpRequest, id: str):
+    """
+    Renders a view for editing compensations
+
+    Args:
+        request (HttpRequest): The incoming request
+
+    Returns:
+
+    """
+    template = "compensation/form/view.html"
+    # Get object from db
+    ema = get_object_or_404(Ema, id=id)
+    if ema.is_recorded:
+        messages.info(
+            request,
+            RECORDED_BLOCKS_EDIT
+        )
+        return redirect("ema:detail", id=id)
+
+    # Create forms, initialize with values from db/from POST request
+    data_form = EditEmaForm(request.POST or None, instance=ema)
+    geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=ema)
+    if request.method == "POST":
+        if data_form.is_valid() and geom_form.is_valid():
+            # The data form takes the geom form for processing, as well as the performing user
+            ema = data_form.save(request.user, geom_form)
+            messages.success(request, _("EMA {} edited").format(ema.identifier))
+            return redirect("ema:detail", id=ema.id)
+        else:
+            messages.error(request, FORM_INVALID, extra_tags="danger",)
+    else:
+        # For clarification: nothing in this case
+        pass
+    context = {
+        "form": data_form,
+        "geom_form": geom_form,
+        TAB_TITLE_IDENTIFIER: _("Edit {}").format(ema.identifier),
+    }
+    context = BaseContext(request, context).context
+    return render(request, template, context)
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def remove_view(request: HttpRequest, id: str):
+    """ Renders a modal view for removing the EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    form = RemoveModalForm(request.POST or None, instance=ema, request=request)
+    return form.process_request(
+        request=request,
+        msg_success=_("EMA removed"),
+        redirect_url=reverse("ema:index"),
+    )
+
diff --git a/ema/views/log.py b/ema/views/log.py
new file mode 100644
index 00000000..3e3f869f
--- /dev/null
+++ b/ema/views/log.py
@@ -0,0 +1,41 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404, render
+from django.utils.translation import gettext_lazy as _
+
+from ema.models import Ema
+from konova.contexts import BaseContext
+from konova.decorators import shared_access_required, conservation_office_group_required
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def log_view(request: HttpRequest, id: str):
+    """ Renders a log view using modal
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    template = "modal/modal_generic.html"
+    body_template = "log.html"
+
+    context = {
+        "modal_body_template": body_template,
+        "log": ema.log.all(),
+        "modal_title": _("Log"),
+    }
+    context = BaseContext(request, context).context
+    return render(request, template, context)
diff --git a/ema/views/record.py b/ema/views/record.py
new file mode 100644
index 00000000..4ae40d2f
--- /dev/null
+++ b/ema/views/record.py
@@ -0,0 +1,37 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404
+from django.utils.translation import gettext_lazy as _
+
+from ema.models import Ema
+from konova.decorators import shared_access_required, conservation_office_group_required
+from konova.forms.modals import RecordModalForm
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def record_view(request: HttpRequest, id: str):
+    """ Renders a modal view for recording the EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    msg_succ = _("{} unrecorded") if ema.recorded else _("{} recorded")
+    form = RecordModalForm(request.POST or None, instance=ema, request=request)
+    return form.process_request(
+        request=request,
+        msg_success=msg_succ.format("EMA"),
+    )
diff --git a/ema/views/report.py b/ema/views/report.py
new file mode 100644
index 00000000..daea0b44
--- /dev/null
+++ b/ema/views/report.py
@@ -0,0 +1,79 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404, render
+from django.urls import reverse
+from django.utils.translation import gettext_lazy as _
+
+from ema.models import Ema
+from konova.contexts import BaseContext
+from konova.forms import SimpleGeomForm
+from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
+from konova.utils.generators import generate_qr_code
+
+
+def report_view(request:HttpRequest, id: str):
+    """ Renders the public report view
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The id of the intervention
+
+    Returns:
+
+    """
+    # Reuse the compensation report template since EMAs are structurally identical
+    template = "ema/report/report.html"
+    ema = get_object_or_404(Ema, id=id)
+
+    tab_title = _("Report {}").format(ema.identifier)
+    # If intervention is not recorded (yet or currently) we need to render another template without any data
+    if not ema.is_ready_for_publish():
+        template = "report/unavailable.html"
+        context = {
+            TAB_TITLE_IDENTIFIER: tab_title,
+        }
+        context = BaseContext(request, context).context
+        return render(request, template, context)
+
+    # Prepare data for map viewer
+    geom_form = SimpleGeomForm(
+        instance=ema,
+    )
+    parcels = ema.get_underlying_parcels()
+
+    qrcode_url = request.build_absolute_uri(reverse("ema:report", args=(id,)))
+    qrcode_img = generate_qr_code(qrcode_url, 10)
+    qrcode_lanis_url = ema.get_LANIS_link()
+    qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
+
+    # Order states by surface
+    before_states = ema.before_states.all().order_by("-surface").prefetch_related("biotope_type")
+    after_states = ema.after_states.all().order_by("-surface").prefetch_related("biotope_type")
+    actions = ema.actions.all().prefetch_related("action_type")
+
+    context = {
+        "obj": ema,
+        "qrcode": {
+            "img": qrcode_img,
+            "url": qrcode_url
+        },
+        "qrcode_lanis": {
+            "img": qrcode_img_lanis,
+            "url": qrcode_lanis_url
+        },
+        "has_access": False,  # disables action buttons during rendering
+        "before_states": before_states,
+        "after_states": after_states,
+        "geom_form": geom_form,
+        "parcels": parcels,
+        "actions": actions,
+        TAB_TITLE_IDENTIFIER: tab_title,
+    }
+    context = BaseContext(request, context).context
+    return render(request, template, context)
diff --git a/ema/views/resubmission.py b/ema/views/resubmission.py
new file mode 100644
index 00000000..838cab3a
--- /dev/null
+++ b/ema/views/resubmission.py
@@ -0,0 +1,39 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404
+from django.urls import reverse
+from django.utils.translation import gettext_lazy as _
+
+from ema.models import Ema
+from konova.decorators import shared_access_required, conservation_office_group_required
+from konova.forms.modals import ResubmissionModalForm
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def create_resubmission_view(request: HttpRequest, id: str):
+    """ Renders resubmission form for an EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): EMA's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    form = ResubmissionModalForm(request.POST or None, instance=ema, request=request)
+    form.action_url = reverse("ema:resubmission-create", args=(id,))
+    return form.process_request(
+        request,
+        msg_success=_("Resubmission set"),
+        redirect_url=reverse("ema:detail", args=(id,))
+    )
diff --git a/ema/views/share.py b/ema/views/share.py
new file mode 100644
index 00000000..83aae91d
--- /dev/null
+++ b/ema/views/share.py
@@ -0,0 +1,77 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib import messages
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404, redirect
+from django.utils.translation import gettext_lazy as _
+
+from ema.models import Ema
+from intervention.forms.modals.share import ShareModalForm
+from konova.decorators import conservation_office_group_required, shared_access_required
+
+
+@login_required
+def share_view(request: HttpRequest, id: str, token: str):
+    """ Performs sharing of an ema
+
+    If token given in url is not valid, the user will be redirected to the dashboard
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): EMA's id
+        token (str): Access token for EMA
+
+    Returns:
+
+    """
+    user = request.user
+    obj = get_object_or_404(Ema, id=id)
+    # Check tokens
+    if obj.access_token == token:
+        # Send different messages in case user has already been added to list of sharing users
+        if obj.is_shared_with(user):
+            messages.info(
+                request,
+                _("{} has already been shared with you").format(obj.identifier)
+            )
+        else:
+            messages.success(
+                request,
+                _("{} has been shared with you").format(obj.identifier)
+            )
+            obj.share_with_user(user)
+        return redirect("ema:detail", id=id)
+    else:
+        messages.error(
+            request,
+            _("Share link invalid"),
+            extra_tags="danger",
+        )
+        return redirect("home")
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def create_share_view(request: HttpRequest, id: str):
+    """ Renders sharing form for an Ema
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): Ema's id
+
+    Returns:
+
+    """
+    obj = get_object_or_404(Ema, id=id)
+    form = ShareModalForm(request.POST or None, instance=obj, request=request)
+    return form.process_request(
+        request,
+        msg_success=_("Share settings updated")
+    )
diff --git a/ema/views/state.py b/ema/views/state.py
new file mode 100644
index 00000000..1c7b0a44
--- /dev/null
+++ b/ema/views/state.py
@@ -0,0 +1,90 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: ksp-servicestelle@sgdnord.rlp.de
+Created on: 19.08.22
+
+"""
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest
+from django.shortcuts import get_object_or_404
+from django.urls import reverse
+
+from compensation.forms.modals.state import NewCompensationStateModalForm, RemoveCompensationStateModalForm, \
+    EditCompensationStateModalForm
+from compensation.models import CompensationState
+from ema.models import Ema
+from konova.decorators import conservation_office_group_required, shared_access_required
+from konova.utils.message_templates import COMPENSATION_STATE_ADDED, COMPENSATION_STATE_REMOVED, \
+    COMPENSATION_STATE_EDITED
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def state_new_view(request: HttpRequest, id: str):
+    """ Renders a form for adding new states for an EMA
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The EMA's id to which the new state will be related
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    form = NewCompensationStateModalForm(request.POST or None, instance=ema, request=request)
+    return form.process_request(
+        request,
+        msg_success=COMPENSATION_STATE_ADDED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def state_remove_view(request: HttpRequest, id: str, state_id: str):
+    """ Renders a form for removing an EMA state
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The ema id
+        state_id (str): The state's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    state = get_object_or_404(CompensationState, id=state_id)
+    form = RemoveCompensationStateModalForm(request.POST or None, instance=ema, state=state, request=request)
+    return form.process_request(
+        request,
+        msg_success=COMPENSATION_STATE_REMOVED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+
+
+@login_required
+@conservation_office_group_required
+@shared_access_required(Ema, "id")
+def state_edit_view(request: HttpRequest, id: str, state_id: str):
+    """ Renders a form for editing an EMA state
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The ema id
+        state_id (str): The state's id
+
+    Returns:
+
+    """
+    ema = get_object_or_404(Ema, id=id)
+    state = get_object_or_404(CompensationState, id=state_id)
+    form = EditCompensationStateModalForm(request.POST or None, instance=ema, state=state, request=request)
+    return form.process_request(
+        request,
+        msg_success=COMPENSATION_STATE_EDITED,
+        redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
+    )
+