#18 File upload in certain folders

* refactors documents and file upload to be distributed into different subfolders, depending on the type of document (InterventionDocument, RevocationDocument, ...)
* refactors Document model into AbstractDocument
* subclasses RevocationDocument, InterventionDocument, COmpensationDocument, EmaDocument and EcoAccountDocument from AbstractDocument to provide proper functionality for each
* adds new specialized routes for each new document type (opening, removing)
* drops generic get and remove routes for documents
This commit is contained in:
mipel
2021-09-01 16:24:49 +02:00
parent 17d574e2a5
commit f64a11cb50
25 changed files with 437 additions and 109 deletions

View File

@@ -21,8 +21,9 @@ urlpatterns = [
path('<id>/deadline/new', deadline_new_view, name="acc-new-deadline"),
# Documents
# Document remove route can be found in konova/urls.py
path('<id>/document/new/', new_document_view, name='acc-new-doc'),
path('document/<doc_id>', get_document_view, name='acc-get-doc'),
path('document/<doc_id>/remove/', remove_document_view, name='acc-remove-doc'),
# Eco-account deductions
path('<id>/remove/<deduction_id>', deduction_remove_view, name='deduction-remove'),

View File

@@ -21,8 +21,9 @@ urlpatterns = [
path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
# Documents
# Document remove route can be found in konova/urls.py
path('<id>/document/new/', new_document_view, name='new-doc'),
path('document/<doc_id>', get_document_view, name='get-doc'),
path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'),
# Generic state routes
path('state/<id>/remove', state_remove_view, name='state-remove'),

View File

@@ -14,7 +14,8 @@ from django.utils.translation import gettext_lazy as _
from codelist.models import KonovaCode
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID
from intervention.models import Intervention, ResponsibilityData
from konova.models import BaseObject, BaseResource, Geometry, UuidModel
from konova.models import BaseObject, BaseResource, Geometry, UuidModel, AbstractDocument, \
generate_document_file_upload_path
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
from user.models import UserActionLogEntry
@@ -137,7 +138,6 @@ class AbstractCompensation(BaseObject):
deadlines = models.ManyToManyField("konova.Deadline", blank=True, related_name="+")
geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
documents = models.ManyToManyField("konova.Document", blank=True)
class Meta:
abstract = True
@@ -198,6 +198,20 @@ class Compensation(AbstractCompensation):
)
class CompensationDocument(AbstractDocument):
"""
Specializes document upload for revocations with certain path
"""
instance = models.ForeignKey(
Compensation,
on_delete=models.CASCADE,
related_name="documents",
)
file = models.FileField(
upload_to=generate_document_file_upload_path
)
class EcoAccount(AbstractCompensation):
"""
An eco account is a kind of 'prepaid' compensation. It can be compared to an account that already has been filled
@@ -299,6 +313,20 @@ class EcoAccount(AbstractCompensation):
return ret_msgs
class EcoAccountDocument(AbstractDocument):
"""
Specializes document upload for revocations with certain path
"""
instance = models.ForeignKey(
EcoAccount,
on_delete=models.CASCADE,
related_name="documents",
)
file = models.FileField(
upload_to=generate_document_file_upload_path
)
class EcoAccountDeduction(BaseResource):
"""
A deduction object for eco accounts

View File

@@ -39,14 +39,14 @@
{% for doc in obj.documents.all %}
<tr>
<td class="align-middle">
<a href="{% url 'doc-open' doc.id %}">
<a href="{% url 'compensation:get-doc' doc.id %}">
{{ doc.title }}
</a>
</td>
<td class="align-middle">{{ doc.comment }}</td>
<td>
{% if is_default_member and has_access %}
<button data-form-url="{% url 'doc-remove' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}">
<button data-form-url="{% url 'compensation:remove-doc' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}">
{% fa5_icon 'trash' %}
</button>
{% endif %}

View File

@@ -39,14 +39,14 @@
{% for doc in obj.documents.all %}
<tr>
<td class="align-middle">
<a href="{% url 'doc-open' doc.id %}">
<a href="{% url 'compensation:acc-get-doc' doc.id %}">
{{ doc.title }}
</a>
</td>
<td class="align-middle">{{ doc.comment }}</td>
<td>
{% if is_default_member and has_access %}
<button data-form-url="{% url 'doc-remove' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}">
<button data-form-url="{% url 'compensation:acc-remove-doc' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}">
{% fa5_icon 'trash' %}
</button>
{% endif %}

View File

@@ -5,11 +5,12 @@ from django.shortcuts import render, get_object_or_404
from django.utils.translation import gettext_lazy as _
from compensation.forms import NewStateModalForm, NewDeadlineModalForm, NewActionModalForm
from compensation.models import Compensation, CompensationState, CompensationAction
from compensation.models import Compensation, CompensationState, CompensationAction, CompensationDocument
from compensation.tables import CompensationTable
from konova.contexts import BaseContext
from konova.decorators import *
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm
from konova.utils.documents import get_document, remove_document
from konova.utils.user_checks import in_group
@@ -163,6 +164,43 @@ def new_document_view(request: HttpRequest, id: str):
)
@login_required
def get_document_view(request: HttpRequest, doc_id: str):
""" Returns the document as downloadable file
Wraps the generic document fetcher function from konova.utils.
Args:
request (HttpRequest): The incoming request
doc_id (str): The document id
Returns:
"""
doc = get_object_or_404(CompensationDocument, id=doc_id)
return get_document(doc)
@login_required
def remove_document_view(request: HttpRequest, 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
doc_id (str): The document id
Returns:
"""
doc = get_object_or_404(CompensationDocument, id=doc_id)
return remove_document(
request,
doc
)
@login_required
def state_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for a compensation

View File

@@ -14,13 +14,14 @@ from django.http import HttpRequest, Http404
from django.shortcuts import render, get_object_or_404
from compensation.forms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm
from compensation.models import EcoAccount
from compensation.models import EcoAccount, EcoAccountDocument
from compensation.tables import EcoAccountTable
from intervention.forms import NewDeductionForm
from konova.contexts import BaseContext
from konova.decorators import any_group_check, default_group_required, conservation_office_group_required
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.utils.documents import get_document, remove_document
from konova.utils.user_checks import in_group
@@ -289,6 +290,43 @@ def new_document_view(request: HttpRequest, id: str):
)
@login_required
def get_document_view(request: HttpRequest, doc_id: str):
""" Returns the document as downloadable file
Wraps the generic document fetcher function from konova.utils.
Args:
request (HttpRequest): The incoming request
doc_id (str): The document id
Returns:
"""
doc = get_object_or_404(EcoAccountDocument, id=doc_id)
return get_document(doc)
@login_required
def remove_document_view(request: HttpRequest, 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
doc_id (str): The document id
Returns:
"""
doc = get_object_or_404(EcoAccountDocument, id=doc_id)
return remove_document(
request,
doc
)
@login_required
@default_group_required
def new_deduction_view(request: HttpRequest, id: str):