Merge pull request 'user_action_log_introduction' (#2) from user_action_log_introduction into master
Reviewed-on: SGD-Nord/konova#2
This commit is contained in:
commit
99bd61935a
@ -18,6 +18,24 @@ class CompensationTableFilter(InterventionTableFilter):
|
||||
|
||||
"""
|
||||
|
||||
def _filter_show_all(self, queryset, name, value) -> QuerySet:
|
||||
""" Filters queryset depending on value of 'show_all' setting
|
||||
|
||||
Args:
|
||||
queryset ():
|
||||
name ():
|
||||
value ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
if not value:
|
||||
return queryset.filter(
|
||||
intervention__users__in=[self.user], # requesting user has access
|
||||
)
|
||||
else:
|
||||
return queryset
|
||||
|
||||
def _filter_show_recorded(self, queryset, name, value) -> QuerySet:
|
||||
""" Filters queryset depending on value of 'show_recorded' setting
|
||||
|
||||
@ -31,7 +49,7 @@ class CompensationTableFilter(InterventionTableFilter):
|
||||
"""
|
||||
if not value:
|
||||
return queryset.filter(
|
||||
intervention__recorded_on=None,
|
||||
intervention__recorded=None,
|
||||
)
|
||||
else:
|
||||
return queryset
|
||||
|
@ -12,8 +12,8 @@ from django.utils import timezone
|
||||
from django.utils.timezone import now
|
||||
|
||||
from compensation.settings import COMPENSATION_IDENTIFIER_LENGTH, COMPENSATION_IDENTIFIER_TEMPLATE
|
||||
from intervention.models import Intervention
|
||||
from konova.models import BaseObject, BaseResource, Geometry
|
||||
from intervention.models import Intervention, ResponsibilityData
|
||||
from konova.models import BaseObject, BaseResource, Geometry, UuidModel
|
||||
from konova.utils.generators import generate_random_string
|
||||
from organisation.models import Organisation
|
||||
|
||||
@ -73,18 +73,19 @@ class Compensation(BaseObject):
|
||||
The compensation holds information about which actions have to be performed until which date, who is in charge
|
||||
of this, which legal authority is the point of contact, and so on.
|
||||
"""
|
||||
registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
|
||||
conservation_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
|
||||
responsible = models.OneToOneField(
|
||||
ResponsibilityData,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Holds data on responsible organizations ('Zulassungsbehörde', 'Eintragungsstelle') and handler",
|
||||
)
|
||||
|
||||
ground_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws!
|
||||
action_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws!
|
||||
before_states = models.ManyToManyField(CompensationState, blank=True, related_name='+', help_text="Refers to 'Ausgangszustand Biotop'")
|
||||
after_states = models.ManyToManyField(CompensationState, blank=True, related_name='+', help_text="Refers to 'Zielzustand Biotop'")
|
||||
actions = models.ManyToManyField(CompensationAction, help_text="Refers to 'Maßnahmen'")
|
||||
|
||||
before_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
||||
after_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
||||
actions = models.ManyToManyField(CompensationAction)
|
||||
|
||||
deadline_creation = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="+")
|
||||
deadline_maintaining = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="+")
|
||||
deadlines = models.ManyToManyField("konova.Deadline", null=True, blank=True, related_name="+")
|
||||
|
||||
geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
|
||||
documents = models.ManyToManyField("konova.Document", blank=True)
|
||||
@ -100,9 +101,6 @@ class Compensation(BaseObject):
|
||||
related_name='compensations'
|
||||
)
|
||||
|
||||
# Users having access on this object
|
||||
users = models.ManyToManyField(User)
|
||||
|
||||
@staticmethod
|
||||
def _generate_new_identifier() -> str:
|
||||
""" Generates a new identifier for the intervention object
|
||||
@ -152,4 +150,5 @@ class EcoAccount(Compensation):
|
||||
An eco account is a kind of 'prepaid' compensation. It can be compared to an account that already has been filled
|
||||
with some kind of currency. From this account one is able to 'withdraw' currency for current projects.
|
||||
"""
|
||||
handler = models.CharField(max_length=500, null=True, blank=True, help_text="Who is responsible for handling the actions")
|
||||
# Users having access on this object
|
||||
users = models.ManyToManyField(User)
|
||||
|
@ -34,13 +34,13 @@ class CompensationTable(BaseTable):
|
||||
verbose_name=_("Checked"),
|
||||
orderable=True,
|
||||
empty_values=[],
|
||||
accessor="intervention__checked_on",
|
||||
accessor="intervention__checked",
|
||||
)
|
||||
r = tables.Column(
|
||||
verbose_name=_("Recorded"),
|
||||
orderable=True,
|
||||
empty_values=[],
|
||||
accessor="intervention__recorded_on",
|
||||
accessor="intervention__recorded",
|
||||
)
|
||||
e = tables.Column(
|
||||
verbose_name=_("Editable"),
|
||||
@ -90,7 +90,7 @@ class CompensationTable(BaseTable):
|
||||
def render_c(self, value, record: Compensation):
|
||||
""" Renders the checked column for a compensation
|
||||
|
||||
checked_on is set by the main object Intervention
|
||||
checked is set by the main object Intervention
|
||||
|
||||
Args:
|
||||
value (str): The identifier value
|
||||
@ -103,9 +103,10 @@ class CompensationTable(BaseTable):
|
||||
checked = value is not None
|
||||
tooltip = _("Not checked yet")
|
||||
if checked:
|
||||
value = value.timestamp
|
||||
value = localtime(value)
|
||||
checked_on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
|
||||
tooltip = _("Checked on {} by {}").format(checked_on, record.intervention.checked_by)
|
||||
tooltip = _("Checked on {} by {}").format(checked_on, record.intervention.checked.user)
|
||||
html += self.render_checked_star(
|
||||
tooltip=tooltip,
|
||||
icn_filled=checked,
|
||||
@ -126,9 +127,10 @@ class CompensationTable(BaseTable):
|
||||
checked = value is not None
|
||||
tooltip = _("Not registered yet")
|
||||
if checked:
|
||||
value = value.timestamp
|
||||
value = localtime(value)
|
||||
on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
|
||||
tooltip = _("Registered on {} by {}").format(on, record.intervention.recorded_by)
|
||||
tooltip = _("Registered on {} by {}").format(on, record.intervention.recorded.user)
|
||||
html += self.render_bookmark(
|
||||
tooltip=tooltip,
|
||||
icn_filled=checked,
|
||||
|
@ -1,17 +1,38 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from intervention.models import Intervention
|
||||
from intervention.models import Intervention, ResponsibilityData, LegalData
|
||||
|
||||
|
||||
class InterventionAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"title",
|
||||
"process_type",
|
||||
"handler",
|
||||
"created_on",
|
||||
"deleted_on",
|
||||
]
|
||||
|
||||
|
||||
class ResponsibilityAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"registration_office",
|
||||
"registration_file_number",
|
||||
"conservation_office",
|
||||
"conservation_file_number",
|
||||
"handler",
|
||||
]
|
||||
|
||||
|
||||
class LegalAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"process_type",
|
||||
"law",
|
||||
"registration_date",
|
||||
"binding_date",
|
||||
]
|
||||
|
||||
|
||||
admin.site.register(Intervention, InterventionAdmin)
|
||||
admin.site.register(ResponsibilityData, ResponsibilityAdmin)
|
||||
admin.site.register(LegalData, LegalAdmin)
|
||||
|
@ -117,7 +117,7 @@ class InterventionTableFilter(django_filters.FilterSet):
|
||||
"""
|
||||
if not value:
|
||||
return queryset.filter(
|
||||
recorded_on=None,
|
||||
recorded=None,
|
||||
)
|
||||
else:
|
||||
return queryset
|
||||
|
@ -12,47 +12,84 @@ from django.utils import timezone
|
||||
from django.utils.timezone import now
|
||||
|
||||
from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_IDENTIFIER_TEMPLATE
|
||||
from konova.models import BaseObject, Geometry
|
||||
from konova.models import BaseObject, Geometry, UuidModel
|
||||
from konova.utils.generators import generate_random_string
|
||||
from organisation.models import Organisation
|
||||
from user.models import UserActionLogEntry
|
||||
|
||||
|
||||
class ResponsibilityData(UuidModel):
|
||||
"""
|
||||
Holds intervention data about responsible organizations and their file numbers for this case
|
||||
|
||||
"""
|
||||
registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
|
||||
registration_file_number = models.CharField(max_length=1000, blank=True, null=True)
|
||||
conservation_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
|
||||
conservation_file_number = models.CharField(max_length=1000, blank=True, null=True)
|
||||
handler = models.CharField(max_length=500, null=True, blank=True, help_text="Refers to 'Eingriffsverursacher'")
|
||||
|
||||
|
||||
class LegalData(UuidModel):
|
||||
"""
|
||||
Holds intervention legal data such as important dates, laws or responsible handler
|
||||
"""
|
||||
# Refers to "zugelassen am"
|
||||
registration_date = models.DateField(null=True, blank=True, help_text="Refers to 'Zugelassen am'")
|
||||
|
||||
# Refers to "Bestandskraft am"
|
||||
binding_date = models.DateField(null=True, blank=True, help_text="Refers to 'Bestandskraft am'")
|
||||
|
||||
process_type = models.CharField(max_length=500, null=True, blank=True)
|
||||
law = models.CharField(max_length=500, null=True, blank=True)
|
||||
|
||||
|
||||
class Intervention(BaseObject):
|
||||
"""
|
||||
Interventions are e.g. construction sites where nature used to be.
|
||||
"""
|
||||
registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
|
||||
registration_file_number = models.CharField(max_length=1000, blank=True, null=True)
|
||||
conservation_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
|
||||
conservation_file_number = models.CharField(max_length=1000, blank=True, null=True)
|
||||
|
||||
process_type = models.CharField(max_length=500, null=True, blank=True)
|
||||
law = models.CharField(max_length=500, null=True, blank=True)
|
||||
handler = models.CharField(max_length=500, null=True, blank=True, help_text="Who is responsible for this intervention?")
|
||||
responsible = models.OneToOneField(
|
||||
ResponsibilityData,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='+',
|
||||
help_text="Holds data on responsible organizations ('Zulassungsbehörde', 'Eintragungsstelle')"
|
||||
)
|
||||
legal = models.OneToOneField(
|
||||
LegalData,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='+',
|
||||
help_text="Holds data on legal dates or law"
|
||||
)
|
||||
geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
|
||||
documents = models.ManyToManyField("konova.Document", blank=True)
|
||||
|
||||
# Checks
|
||||
checked_on = models.DateTimeField(default=None, null=True, blank=True)
|
||||
checked_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, related_name='+')
|
||||
|
||||
# Refers to "zugelassen am"
|
||||
registration_date = models.DateField(null=True, blank=True)
|
||||
|
||||
# Refers to "Bestandskraft am"
|
||||
binding_on = models.DateField(null=True, blank=True)
|
||||
# Checks - Refers to "Genehmigen" but optional
|
||||
checked = models.OneToOneField(
|
||||
UserActionLogEntry,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Holds data on user and timestamp of this action",
|
||||
related_name="+"
|
||||
)
|
||||
|
||||
# Refers to "verzeichnen"
|
||||
recorded_on = models.DateTimeField(default=None, null=True, blank=True)
|
||||
recorded_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, related_name='+')
|
||||
recorded = models.OneToOneField(
|
||||
UserActionLogEntry,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Holds data on user and timestamp of this action",
|
||||
related_name="+"
|
||||
)
|
||||
|
||||
# Holds which intervention is simply a newer version of this dataset
|
||||
next_version = models.ForeignKey("Intervention", null=True, blank=True, on_delete=models.DO_NOTHING)
|
||||
|
||||
# Compensation or payments, one-directional
|
||||
#payments = models.ManyToManyField(Payment, related_name="+", blank=True)
|
||||
#compensations = models.ManyToManyField(Compensation, related_name="+", blank=True)
|
||||
|
||||
# Users having access on this object
|
||||
users = models.ManyToManyField(User)
|
||||
|
||||
|
@ -33,13 +33,13 @@ class InterventionTable(BaseTable):
|
||||
verbose_name=_("Checked"),
|
||||
orderable=True,
|
||||
empty_values=[],
|
||||
accessor="checked_on",
|
||||
accessor="checked",
|
||||
)
|
||||
r = tables.Column(
|
||||
verbose_name=_("Recorded"),
|
||||
orderable=True,
|
||||
empty_values=[],
|
||||
accessor="recorded_on",
|
||||
accessor="recorded",
|
||||
)
|
||||
e = tables.Column(
|
||||
verbose_name=_("Editable"),
|
||||
@ -110,9 +110,10 @@ class InterventionTable(BaseTable):
|
||||
checked = value is not None
|
||||
tooltip = _("Not checked yet")
|
||||
if checked:
|
||||
value = value.timestamp
|
||||
value = localtime(value)
|
||||
checked_on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
|
||||
tooltip = _("Checked on {} by {}").format(checked_on, record.checked_by)
|
||||
tooltip = _("Checked on {} by {}").format(checked_on, record.checked.user)
|
||||
html += self.render_checked_star(
|
||||
tooltip=tooltip,
|
||||
icn_filled=checked,
|
||||
@ -133,9 +134,10 @@ class InterventionTable(BaseTable):
|
||||
checked = value is not None
|
||||
tooltip = _("Not registered yet")
|
||||
if checked:
|
||||
value = value.timestamp
|
||||
value = localtime(value)
|
||||
on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
|
||||
tooltip = _("Registered on {} by {}").format(on, record.recorded_by)
|
||||
tooltip = _("Registered on {} by {}").format(on, record.recorded.user)
|
||||
html += self.render_bookmark(
|
||||
tooltip=tooltip,
|
||||
icn_filled=checked,
|
||||
|
@ -64,41 +64,41 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Process type' %}</th>
|
||||
<td class="align-middle">{{intervention.process_type|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.legal.process_type|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Law' %}</th>
|
||||
<td class="align-middle">{{intervention.law|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.legal.law|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Registration office' %}</th>
|
||||
<td class="align-middle">{{intervention.registration_office|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.responsible.registration_office|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Registration office file number' %}</th>
|
||||
<td class="align-middle">{{intervention.registration_file_number|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.responsible.registration_file_number|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Conservation office' %}</th>
|
||||
<td class="align-middle">{{intervention.conservation_office|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.responsible.conservation_office|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Conversation office file number' %}</th>
|
||||
<td class="align-middle">{{intervention.conservation_file_number|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.responsible.conservation_file_number|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Intervention handler' %}</th>
|
||||
<td class="align-middle">{{intervention.handler|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.responsible.handler|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Checked' %}</th>
|
||||
<td class="align-middle">
|
||||
{% if intervention.checked_on is None %}
|
||||
{% if intervention.checked is None %}
|
||||
<span>
|
||||
{% fa5_icon 'star' 'far' %}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="check-star">
|
||||
<span class="check-star" title="{% trans 'Checked on '%} {{intervention.checked.timestamp}} {% trans 'by' %} {{intervention.checked.user}}">
|
||||
{% fa5_icon 'star' %}
|
||||
</span>
|
||||
{% endif %}
|
||||
@ -107,12 +107,12 @@
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Recorded' %}</th>
|
||||
<td class="align-middle">
|
||||
{% if intervention.recorded_on is None %}
|
||||
{% if intervention.recorded is None %}
|
||||
<span>
|
||||
{% fa5_icon 'bookmark' 'far' %}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="registered-bookmark">
|
||||
<span class="registered-bookmark" title="{% trans 'Recorded on '%} {{intervention.recorded.timestamp}} {% trans 'by' %} {{intervention.recorded.user}}">
|
||||
{% fa5_icon 'bookmark' %}
|
||||
</span>
|
||||
{% endif %}
|
||||
@ -120,11 +120,11 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Registration date' %}</th>
|
||||
<td class="align-middle">{{intervention.registration_date|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.legal.registration_date|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Binding on' %}</th>
|
||||
<td class="align-middle">{{intervention.binding_on|default_if_none:""}}</td>
|
||||
<td class="align-middle">{{intervention.legal.binding_on|default_if_none:""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Last modified' %}</th>
|
||||
|
@ -7,7 +7,7 @@ Created on: 22.07.21
|
||||
"""
|
||||
from django.contrib import admin
|
||||
|
||||
from konova.models import Geometry, Document
|
||||
from konova.models import Geometry, Document, Deadline
|
||||
|
||||
|
||||
class GeometryAdmin(admin.ModelAdmin):
|
||||
@ -28,5 +28,15 @@ class DocumentAdmin(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
class DeadlineAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"type",
|
||||
"date",
|
||||
"comment",
|
||||
]
|
||||
|
||||
|
||||
admin.site.register(Geometry, GeometryAdmin)
|
||||
admin.site.register(Document, DocumentAdmin)
|
||||
admin.site.register(Deadline, DeadlineAdmin)
|
||||
|
@ -47,3 +47,17 @@ class ServerMessageImportance(BaseEnum):
|
||||
DEFAULT = "DEFAULT"
|
||||
INFO = "INFO"
|
||||
WARNING = "WARNING"
|
||||
|
||||
|
||||
class UserActionLogEntryEnum(BaseEnum):
|
||||
"""
|
||||
Defines different possible user actions for UserActionLogEntry
|
||||
"""
|
||||
CHECKED = "Checked"
|
||||
RECORDED = "Recorded"
|
||||
|
||||
|
||||
class DeadlineTypeEnum(BaseEnum):
|
||||
MAINTAIN = "Maintain"
|
||||
CONTROL = "Control"
|
||||
OTHER = "Other"
|
@ -12,17 +12,27 @@ from django.contrib.auth.models import User
|
||||
from django.contrib.gis.db.models import MultiPolygonField
|
||||
from django.db import models
|
||||
|
||||
from konova.enums import DeadlineTypeEnum
|
||||
from konova.settings import DEFAULT_SRID
|
||||
|
||||
|
||||
class BaseResource(models.Model):
|
||||
class UuidModel(models.Model):
|
||||
"""
|
||||
A basic resource model, which defines attributes for every derived model
|
||||
Encapsules identifying via uuid
|
||||
"""
|
||||
id = models.UUIDField(
|
||||
primary_key=True,
|
||||
default=uuid.uuid4,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class BaseResource(UuidModel):
|
||||
"""
|
||||
A basic resource model, which defines attributes for every derived model
|
||||
"""
|
||||
created_on = models.DateTimeField(auto_now_add=True, null=True)
|
||||
created_by = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, related_name="+")
|
||||
|
||||
@ -50,8 +60,9 @@ class Deadline(BaseResource):
|
||||
"""
|
||||
Defines a deadline, which can be used to define dates with a semantic meaning
|
||||
"""
|
||||
type = models.CharField(max_length=500, null=True, blank=True)
|
||||
type = models.CharField(max_length=255, null=True, blank=True, choices=DeadlineTypeEnum.as_choices(drop_empty_choice=True))
|
||||
date = models.DateField(null=True, blank=True)
|
||||
comment = models.CharField(max_length=1000, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.type
|
||||
|
@ -78,7 +78,7 @@ def home_view(request: HttpRequest):
|
||||
next_version=None,
|
||||
)
|
||||
user_comps = comps.filter(
|
||||
users__in=[user]
|
||||
intervention__users__in=[user]
|
||||
)
|
||||
eco_accs = EcoAccount.objects.filter(
|
||||
deleted_on=None,
|
||||
|
@ -1,6 +1,6 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from user.models import UserNotification, KonovaUserExtension
|
||||
from user.models import UserNotification, KonovaUserExtension, UserActionLogEntry
|
||||
|
||||
|
||||
class UserNotificationAdmin(admin.ModelAdmin):
|
||||
@ -17,5 +17,15 @@ class KonovaUserExtensionAdmin(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
class UserActionLogEntryAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"user",
|
||||
"timestamp",
|
||||
"action",
|
||||
]
|
||||
|
||||
|
||||
admin.site.register(UserNotification, UserNotificationAdmin)
|
||||
admin.site.register(KonovaUserExtension, KonovaUserExtensionAdmin)
|
||||
admin.site.register(UserActionLogEntry, UserActionLogEntryAdmin)
|
@ -1,6 +1,9 @@
|
||||
import uuid
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
|
||||
from konova.enums import UserActionLogEntryEnum
|
||||
from user.enums import UserNotificationEnum
|
||||
|
||||
|
||||
@ -36,3 +39,27 @@ class KonovaUserExtension(models.Model):
|
||||
"""
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
notifications = models.ManyToManyField(UserNotification, related_name="+")
|
||||
|
||||
|
||||
class UserActionLogEntry(models.Model):
|
||||
""" Wraps a user action log entry
|
||||
|
||||
Can be used for workflow related attributes like checking or recording.
|
||||
|
||||
"""
|
||||
id = models.UUIDField(
|
||||
primary_key=True,
|
||||
default=uuid.uuid4,
|
||||
)
|
||||
user = models.ForeignKey(User, related_name='+', on_delete=models.CASCADE, help_text="Performing user")
|
||||
timestamp = models.DateTimeField(auto_now_add=True, help_text="Timestamp of performed action")
|
||||
action = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Short name for performed action - optional",
|
||||
choices=UserActionLogEntryEnum.as_choices(drop_empty_choice=True),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return "{} | {} | {}".format(self.user.username, self.timestamp, self.action)
|
Loading…
Reference in New Issue
Block a user