Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request #25 from inspirehep/author-wf-status
Browse files Browse the repository at this point in the history
update workflow models
  • Loading branch information
MJedr authored Dec 7, 2023
2 parents 07f8d6f + d6111ea commit c28e170
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 39 deletions.
8 changes: 7 additions & 1 deletion backoffice/workflows/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
from rest_framework import serializers

from backoffice.workflows.models import Workflow
from backoffice.workflows.models import Workflow, WorkflowTicket


class WorkflowSerializer(serializers.ModelSerializer):
class Meta:
model = Workflow
fields = "__all__"


class WorkflowTicketSerializer(serializers.ModelSerializer):
class Meta:
model = WorkflowTicket
fields = "__all__"
23 changes: 21 additions & 2 deletions backoffice/workflows/api/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from django.shortcuts import get_object_or_404
from rest_framework import status, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView

from backoffice.workflows.models import Workflow
from backoffice.workflows.models import Workflow, WorkflowTicket

from .serializers import WorkflowSerializer
from .serializers import WorkflowSerializer, WorkflowTicketSerializer


class WorkflowViewSet(viewsets.ModelViewSet):
Expand All @@ -27,3 +28,21 @@ def partial_update(self, request, pk=None):
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class WorkflowTicketViewSet(viewsets.ViewSet):
def retrieve(self, request, *args, **kwargs):
workflow_id = kwargs.get("pk")
ticket_type = request.query_params.get("ticket_type")

if not workflow_id or not ticket_type:
return Response(
{"error": "Both workflow_id and ticket_type are required."}, status=status.HTTP_400_BAD_REQUEST
)

try:
workflow_ticket = WorkflowTicket.objects.get(workflow_id=workflow_id, ticket_type=ticket_type)
serializer = WorkflowTicketSerializer(workflow_ticket)
return Response(serializer.data)
except WorkflowTicket.DoesNotExist:
return Response({"error": "Workflow ticket not found."}, status=status.HTTP_404_NOT_FOUND)
23 changes: 23 additions & 0 deletions backoffice/workflows/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# tickets
TICKET_TYPES = (
("author_create_curation", "Author create curation"),
("author_create_user", "Author create user"),
)
DEFAULT_TICKET_TYPE = "author_create_curation"

# workflows
DEFAULT_STATUS_CHOICE = "running"
DEFAULT_WORKFLOW_TYPE = "HEP_create"
STATUS_CHOICES = (
("running", "Running"),
("approval", "Waiting for approval"),
("completed", "Completed"),
("error", "Error"),
)

WORKFLOW_TYPES = (
("HEP_CREATE", "HEP create"),
("HEP_UPDATE", "HEP update"),
("AUTHOR_CREATE", "Author create"),
("AUTHOR_UPDATE", "Author update"),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 4.2.6 on 2023-12-07 14:57

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("workflows", "0004_workflow_workflow_type"),
]

operations = [
migrations.AddField(
model_name="workflowticket",
name="ticket_type",
field=models.CharField(
choices=[
("author_create_curation", "Author create curation"),
("author_create_user", "Author create user"),
],
default="author_create_curation",
max_length=30,
),
),
migrations.AlterField(
model_name="workflow",
name="status",
field=models.CharField(
choices=[
("running", "Running"),
("approval", "Waiting for approval"),
("completed", "Completed"),
("error", "Error"),
],
default="running",
max_length=30,
),
),
]
24 changes: 10 additions & 14 deletions backoffice/workflows/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@

from django.db import models

from .constants import (
DEFAULT_STATUS_CHOICE,
DEFAULT_TICKET_TYPE,
DEFAULT_WORKFLOW_TYPE,
STATUS_CHOICES,
TICKET_TYPES,
WORKFLOW_TYPES,
)

class Workflow(models.Model):
DEFAULT_STATUS_CHOICE = "PREPROCESSING"
DEFAULT_WORKFLOW_TYPE = "HEP_create"
STATUS_CHOICES = (
("PREPROCESSING", "Preprocessing"),
("APPROVAL", "Approval"),
("POSTPROCESSING", "Postprocessing"),
)

WORKFLOW_TYPES = (
("HEP_CREATE", "HEP create"),
("HEP_UPDATE", "HEP update"),
("AUTHOR_CREATE", "Author create"),
("AUTHOR_UPDATE", "Author update"),
)
class Workflow(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

workflow_type = models.CharField(
Expand All @@ -38,3 +33,4 @@ class Workflow(models.Model):
class WorkflowTicket(models.Model):
workflow_id = models.ForeignKey(Workflow, on_delete=models.CASCADE)
ticket_id = models.CharField(max_length=32) # in SNOW it's GUID
ticket_type = models.CharField(max_length=30, choices=TICKET_TYPES, default=DEFAULT_TICKET_TYPE)
85 changes: 65 additions & 20 deletions backoffice/workflows/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import pytest
from django.apps import apps
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.test import TransactionTestCase
from rest_framework.test import APIClient

from backoffice.workflows.api.serializers import WorkflowTicketSerializer
from backoffice.workflows.models import WorkflowTicket

User = get_user_model()
Workflow = apps.get_model(app_label="workflows", model_name="Workflow")


class TestWorkflowViewSet(TransactionTestCase):
endpoint = "/api/workflows/"
class BaseTransactionTestCase(TransactionTestCase):
reset_sequences = True
fixtures = ["backoffice/fixtures/groups.json"]

Expand All @@ -25,7 +28,16 @@ def setUp(self):
self.admin.groups.add(self.admin_group)

self.api_client = APIClient()
self.workflow = Workflow.objects.create(data={}, status="APPROVAL", core=True, is_update=False)


class TestWorkflowViewSet(BaseTransactionTestCase):
endpoint = "/api/workflows/"
reset_sequences = True
fixtures = ["backoffice/fixtures/groups.json"]

def setUp(self):
super().setUp()
self.workflow = Workflow.objects.create(data={}, status="approval", core=True, is_update=False)

def test_list_curator(self):
self.api_client.force_authenticate(user=self.curator)
Expand All @@ -48,50 +60,83 @@ def test_list_anonymous(self):
self.assertEqual(response.status_code, 403)


class WorkflowPartialUpdateViewSet(TransactionTestCase):
class TestWorkflowPartialUpdateViewSet(BaseTransactionTestCase):
endpoint_base_url = "/api/workflow-update"
reset_sequences = True
fixtures = ["backoffice/fixtures/groups.json"]

def setUp(self):
self.curator_group = Group.objects.get(name="curator")
self.admin_group = Group.objects.get(name="admin")

self.curator = User.objects.create_user(email="[email protected]", password="12345")
self.admin = User.objects.create_user(email="[email protected]", password="12345")
self.user = User.objects.create_user(email="[email protected]", password="12345")

self.curator.groups.add(self.curator_group)
self.admin.groups.add(self.admin_group)

self.api_client = APIClient()
self.workflow = Workflow.objects.create(data={}, status="APPROVAL", core=True, is_update=False)
super().setUp()
self.workflow = Workflow.objects.create(data={}, status="approval", core=True, is_update=False)

@property
def endpoint(self):
return f"{self.endpoint_base_url}/{self.workflow.id}/"

def test_patch_curator(self):
self.api_client.force_authenticate(user=self.curator)
response = self.api_client.patch(self.endpoint, format="json", data={"status": "POSTPROCESSING"})
response = self.api_client.patch(self.endpoint, format="json", data={"status": "running"})

self.assertEqual(response.status_code, 200)
workflow = Workflow.objects.filter(id=str(self.workflow.id))[0]
assert workflow.status == "POSTPROCESSING"
assert workflow.status == "running"

def test_patch_admin(self):
self.api_client.force_authenticate(user=self.admin)
response = self.api_client.patch(
self.endpoint, format="json", data={"status": "PREPROCESSING", "data": {"test": "test"}}
self.endpoint, format="json", data={"status": "approval", "data": {"test": "test"}}
)

workflow = Workflow.objects.filter(id=str(self.workflow.id))[0]
self.assertEqual(response.status_code, 200)
self.assertEquals(workflow.status, "PREPROCESSING")
self.assertEquals(workflow.status, "approval")
self.assertEquals(workflow.data, {"test": "test"})

def test_patch_anonymous(self):
self.api_client.force_authenticate(user=self.user)
response = self.api_client.get(self.endpoint, format="json")

self.assertEqual(response.status_code, 403)


class TestWorkflowTicketViewSet(BaseTransactionTestCase):
endpoint = "/api/workflow-ticket"
reset_sequences = True
fixtures = ["backoffice/fixtures/groups.json"]

def setUp(self):
super().setUp()
self.workflow = Workflow.objects.create(data={}, status="running", core=True, is_update=False)
self.workflow_ticket = WorkflowTicket.objects.create(
workflow_id=self.workflow, ticket_id="123", ticket_type="author_create_user"
)

def test_get_missing_params(self):
self.api_client.force_authenticate(user=self.curator)
response = self.api_client.get(
f"{TestWorkflowTicketViewSet.endpoint}/{self.workflow.id}/", format="json", data={}
)

assert response.status_code == 400
assert response.data == {"error": "Both workflow_id and ticket_type are required."}

def test_get_ticket_not_found(self):
query_params = {"ticket_type": "test"}
self.api_client.force_authenticate(user=self.curator)
response = self.api_client.get(
f"{TestWorkflowTicketViewSet.endpoint}/{self.workflow.id}/", format="json", data=query_params
)

assert response.status_code == 404
assert response.data == {"error": "Workflow ticket not found."}

def test_get_ticket_happy_flow(self):
self.api_client.force_authenticate(user=self.curator)

query_params = {"ticket_type": self.workflow_ticket.ticket_type}
response = self.api_client.get(
f"{TestWorkflowTicketViewSet.endpoint}/{self.workflow.id}/", format="json", data=query_params
)

assert response.status_code == 200
assert response.data == WorkflowTicketSerializer(self.workflow_ticket).data
4 changes: 2 additions & 2 deletions config/api_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from rest_framework.routers import DefaultRouter, SimpleRouter

from backoffice.users.api.views import UserViewSet
from backoffice.workflows.api.views import WorkflowPartialUpdateViewSet, WorkflowViewSet
from backoffice.workflows.api.views import WorkflowPartialUpdateViewSet, WorkflowTicketViewSet, WorkflowViewSet

if settings.DEBUG:
router = DefaultRouter()
Expand All @@ -14,6 +14,6 @@
# Workflows
router.register("workflows", WorkflowViewSet, basename="workflows")
router.register("workflow-update", WorkflowPartialUpdateViewSet, basename="workflow-update")

router.register("workflow-ticket", WorkflowTicketViewSet, basename="workflow-ticket"),
app_name = "api"
urlpatterns = router.urls

0 comments on commit c28e170

Please sign in to comment.