mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 17:26:10 -06:00
review request model
This commit is contained in:
parent
1f70360592
commit
59c99ddbfe
@ -11,7 +11,7 @@ from dcim.api.nested_serializers import (
|
|||||||
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
||||||
from extras.choices import *
|
from extras.choices import *
|
||||||
from extras.models import *
|
from extras.models import *
|
||||||
from extras.models.staging import Notification
|
from extras.models.staging import Notification, ReviewRequest
|
||||||
from extras.utils import FeatureQuery
|
from extras.utils import FeatureQuery
|
||||||
from netbox.api.exceptions import SerializerNotFound
|
from netbox.api.exceptions import SerializerNotFound
|
||||||
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
|
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
|
||||||
@ -537,3 +537,16 @@ class NotificationSerializer(BaseModelSerializer):
|
|||||||
fields = [
|
fields = [
|
||||||
'id', 'url', 'created', 'title', 'content', 'read'
|
'id', 'url', 'created', 'title', 'content', 'read'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewRequestSerializer(BaseModelSerializer):
|
||||||
|
url = serializers.HyperlinkedIdentityField(view_name='extras-api:review-requests-detail')
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ReviewRequest
|
||||||
|
fields = [
|
||||||
|
'id', 'url', 'created', 'last_updated', 'owner', 'reviewer', 'branch', 'status', 'state'
|
||||||
|
]
|
||||||
|
@ -20,6 +20,7 @@ router.register('object-changes', views.ObjectChangeViewSet)
|
|||||||
router.register('job-results', views.JobResultViewSet)
|
router.register('job-results', views.JobResultViewSet)
|
||||||
router.register('content-types', views.ContentTypeViewSet)
|
router.register('content-types', views.ContentTypeViewSet)
|
||||||
router.register('notifications', views.NotificationViewSet, basename='notifications')
|
router.register('notifications', views.NotificationViewSet, basename='notifications')
|
||||||
|
router.register('review-requests', views.ReviewRequestViewSet, basename='review-requests')
|
||||||
|
|
||||||
app_name = 'extras-api'
|
app_name = 'extras-api'
|
||||||
urlpatterns = router.urls
|
urlpatterns = router.urls
|
||||||
|
@ -15,7 +15,7 @@ from extras import filtersets
|
|||||||
from extras.choices import JobResultStatusChoices
|
from extras.choices import JobResultStatusChoices
|
||||||
from extras.models import *
|
from extras.models import *
|
||||||
from extras.models import CustomField
|
from extras.models import CustomField
|
||||||
from extras.models.staging import Notification
|
from extras.models.staging import Notification, ReviewRequest
|
||||||
from extras.reports import get_report, get_reports, run_report
|
from extras.reports import get_report, get_reports, run_report
|
||||||
from extras.scripts import get_script, get_scripts, run_script
|
from extras.scripts import get_script, get_scripts, run_script
|
||||||
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
|
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
|
||||||
@ -406,6 +406,7 @@ class NotificationViewSet(ReadOnlyModelViewSet):
|
|||||||
serializer_class = serializers.NotificationSerializer
|
serializer_class = serializers.NotificationSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
# TODO: Maybe we want to drop the filter if an admin is querying.
|
||||||
return Notification.objects.filter(user__id=self.request.user.id).order_by('created')
|
return Notification.objects.filter(user__id=self.request.user.id).order_by('created')
|
||||||
|
|
||||||
def partial_update(self, request, pk=None):
|
def partial_update(self, request, pk=None):
|
||||||
@ -419,3 +420,15 @@ class NotificationViewSet(ReadOnlyModelViewSet):
|
|||||||
n = get_object_or_404(self.get_queryset(), pk=pk)
|
n = get_object_or_404(self.get_queryset(), pk=pk)
|
||||||
n.delete()
|
n.delete()
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewRequestViewSet(ReadOnlyModelViewSet):
|
||||||
|
|
||||||
|
permission_classes = [IsAuthenticatedOrLoginNotRequired]
|
||||||
|
serializer_class = serializers.ReviewRequestSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return ReviewRequest.objects.filter(owner__id=self.request.user.id).order_by('last_updated')
|
||||||
|
|
||||||
|
def create(self, create):
|
||||||
|
pass
|
||||||
|
@ -199,3 +199,27 @@ class ChangeActionChoices(ChoiceSet):
|
|||||||
(ACTION_UPDATE, 'Update'),
|
(ACTION_UPDATE, 'Update'),
|
||||||
(ACTION_DELETE, 'Delete'),
|
(ACTION_DELETE, 'Delete'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewRequestStateChoices(ChoiceSet):
|
||||||
|
|
||||||
|
STATE_UNDER_REVIEW = 'under_review'
|
||||||
|
STATE_APPROVED = 'approved'
|
||||||
|
STATE_DENIED = 'denied'
|
||||||
|
|
||||||
|
CHOICES = (
|
||||||
|
(STATE_UNDER_REVIEW, 'Under Review'),
|
||||||
|
(STATE_APPROVED, 'Approved'),
|
||||||
|
(STATE_DENIED, 'Denied')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewRequestStatusChoices(ChoiceSet):
|
||||||
|
|
||||||
|
STATUS_OPEN = 'open'
|
||||||
|
STATUS_CLOSED = 'closed'
|
||||||
|
|
||||||
|
CHOICES = (
|
||||||
|
(STATUS_OPEN, 'Open'),
|
||||||
|
(STATUS_CLOSED, 'Closed')
|
||||||
|
)
|
||||||
|
@ -7,7 +7,9 @@ from django.db import models, transaction
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from extras.choices import ChangeActionChoices
|
from extras.choices import ChangeActionChoices, \
|
||||||
|
ReviewRequestStateChoices, \
|
||||||
|
ReviewRequestStatusChoices
|
||||||
from netbox.models import ChangeLoggedModel, NetBoxModel
|
from netbox.models import ChangeLoggedModel, NetBoxModel
|
||||||
from utilities.utils import deserialize_object
|
from utilities.utils import deserialize_object
|
||||||
|
|
||||||
@ -147,3 +149,45 @@ class Notification(NetBoxModel):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('pk',)
|
ordering = ('pk',)
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewRequest(ChangeLoggedModel):
|
||||||
|
|
||||||
|
owner = models.ForeignKey(
|
||||||
|
settings.AUTH_USER_MODEL,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name='review_requests'
|
||||||
|
)
|
||||||
|
|
||||||
|
reviewer = models.ForeignKey(
|
||||||
|
settings.AUTH_USER_MODEL,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name='assigned_review_requests'
|
||||||
|
)
|
||||||
|
|
||||||
|
branch = models.ForeignKey(
|
||||||
|
to=Branch,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name='review_request'
|
||||||
|
)
|
||||||
|
|
||||||
|
status = models.CharField(
|
||||||
|
max_length=256,
|
||||||
|
choices=ReviewRequestStatusChoices,
|
||||||
|
default=ReviewRequestStatusChoices.STATUS_OPEN
|
||||||
|
)
|
||||||
|
|
||||||
|
state = models.CharField(
|
||||||
|
max_length=256,
|
||||||
|
choices=ReviewRequestStateChoices,
|
||||||
|
default=ReviewRequestStateChoices.STATE_UNDER_REVIEW
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'[OwnerId: {self.owner.pk}, ReviewerId: {self.reviewer.id} {self.status}/{self.state}] {self.branch}'
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse('extras-api:review-requests-detail', args=[self.pk])
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ('pk',)
|
||||||
|
Loading…
Reference in New Issue
Block a user