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

Commit

Permalink
author decisions: shared task added
Browse files Browse the repository at this point in the history
  • Loading branch information
DonHaul committed Aug 13, 2024
1 parent aecd899 commit 6a6bfc2
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 13 deletions.
8 changes: 7 additions & 1 deletion backoffice/backoffice/workflows/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from backoffice.workflows.constants import ResolutionDags, StatusChoices, WorkflowType
from backoffice.workflows.documents import WorkflowDocument
from backoffice.workflows.models import Workflow, WorkflowTicket
from backoffice.workflows.models import Decision, Workflow, WorkflowTicket


class WorkflowSerializer(serializers.ModelSerializer):
Expand All @@ -19,6 +19,12 @@ class Meta:
fields = "__all__"


class DecisionSerializer(serializers.ModelSerializer):
class Meta:
model = Decision
fields = "__all__"


class WorkflowDocumentSerializer(DocumentSerializer):
class Meta:
document = WorkflowDocument
Expand Down
40 changes: 39 additions & 1 deletion backoffice/backoffice/workflows/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from backoffice.workflows import airflow_utils
from backoffice.workflows.api.serializers import (
AuthorResolutionSerializer,
DecisionSerializer,
WorkflowAuthorSerializer,
WorkflowDocumentSerializer,
WorkflowSerializer,
Expand All @@ -37,7 +38,7 @@
WorkflowType,
)
from backoffice.workflows.documents import WorkflowDocument
from backoffice.workflows.models import Workflow, WorkflowTicket
from backoffice.workflows.models import Decision, Workflow, WorkflowTicket

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -100,6 +101,43 @@ def create(self, request, *args, **kwargs):
)


class DecisionViewSet(viewsets.ViewSet):
def retrieve(self, request, *args, **kwargs):
workflow_id = kwargs.get("pk")
try:
decision = Decision.objects.get(workflow_id=workflow_id)
serializer = DecisionSerializer(decision)
return Response(serializer.data)
except Decision.DoesNotExist:
return Response(
{"error": "Workflow ticket not found."},
status=status.HTTP_404_NOT_FOUND,
)

def create(self, request, *args, **kwargs):
workflow_id = request.data.get("workflow_id")
action = request.data.get("action")
user_id = request.data.get("user_id")

if not all([workflow_id, action, user_id]):
return Response(
{"error": "Workflow_id, ticket_id and ticket_type are required."},
status=status.HTTP_400_BAD_REQUEST,
)

try:
workflow = Workflow.objects.get(id=workflow_id)
decision = Decision.objects.create(
workflow_id=workflow, user_id=user_id, action=action
)
serializer = DecisionSerializer(decision)
return Response(serializer.data, status=status.HTTP_201_CREATED)
except Exception as e:
return Response(
{"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
)


class AuthorWorkflowViewSet(viewsets.ViewSet):
serializer_class = WorkflowAuthorSerializer

Expand Down
1 change: 1 addition & 0 deletions backoffice/backoffice/workflows/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class WorkflowType(models.TextChoices):
class ResolutionDags(models.TextChoices):
accept = "accept", "author_create_approved_dag"
reject = "reject", "author_create_rejected_dag"
accept_curate = "accept_curate", "author_create_approved_dag"


class AuthorCreateDags(models.TextChoices):
Expand Down
56 changes: 56 additions & 0 deletions backoffice/backoffice/workflows/migrations/0009_decision.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 4.2.6 on 2024-08-13 08:38

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("workflows", "0008_alter_workflow_status_alter_workflow_workflow_type"),
]

operations = [
migrations.CreateModel(
name="Decision",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"action",
models.CharField(
choices=[
("accept", "author_create_approved_dag"),
("reject", "author_create_rejected_dag"),
("accept_curate", "author_create_approved_dag"),
],
max_length=30,
),
),
("_created_at", models.DateTimeField(auto_now_add=True)),
("_updated_at", models.DateTimeField(auto_now=True)),
(
"user_id",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
(
"workflow_id",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="workflows.workflow",
),
),
],
),
]
11 changes: 11 additions & 0 deletions backoffice/backoffice/workflows/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

from django.db import models

from backoffice.users.models import User
from backoffice.workflows.constants import (
DEFAULT_STATUS_CHOICE,
DEFAULT_TICKET_TYPE,
DEFAULT_WORKFLOW_TYPE,
TICKET_TYPES,
ResolutionDags,
StatusChoices,
WorkflowType,
)
Expand Down Expand Up @@ -41,3 +43,12 @@ class WorkflowTicket(models.Model):
ticket_type = models.CharField(
max_length=30, choices=TICKET_TYPES, default=DEFAULT_TICKET_TYPE
)


class Decision(models.Model):
user_id = models.ForeignKey(User, on_delete=models.CASCADE)
workflow_id = models.ForeignKey(Workflow, on_delete=models.CASCADE)
action = models.CharField(max_length=30, choices=ResolutionDags.choices)

_created_at = models.DateTimeField(auto_now_add=True)
_updated_at = models.DateTimeField(auto_now=True)
2 changes: 2 additions & 0 deletions backoffice/config/api_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from backoffice.users.api.views import UserViewSet
from backoffice.workflows.api.views import (
AuthorWorkflowViewSet,
DecisionViewSet,
WorkflowTicketViewSet,
WorkflowViewSet,
)
Expand All @@ -20,5 +21,6 @@
)
router.register("workflows", WorkflowViewSet, basename="workflows")
(router.register("workflow-ticket", WorkflowTicketViewSet, basename="workflow-ticket"),)
router.register("decision", DecisionViewSet, basename="decisions")
app_name = "api"
urlpatterns = router.urls
Empty file added workflows/__init__.py
Empty file.
19 changes: 9 additions & 10 deletions workflows/dags/author/author_create/author_create_approved.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from airflow.decorators import dag, task
from airflow.models.param import Param
from airflow.utils.trigger_rule import TriggerRule
from author.author_create.shared_tasks import create_decision_on_curation_choice
from hooks.backoffice.workflow_management_hook import AUTHORS, WorkflowManagementHook
from hooks.backoffice.workflow_ticket_management_hook import (
WorkflowTicketManagementHook,
Expand Down Expand Up @@ -167,20 +168,18 @@ def set_author_create_workflow_status_to_error(**context: dict) -> None:
set_workflow_status_to_error_task = set_author_create_workflow_status_to_error()
combine_ticket_and_no_ticket_task = empty_task()

combine_ticket_and_no_ticket_task = empty_task()

complete_task = [
create_decision_on_curation_choice() >> set_workflow_status_to_completed_task
]

# task dependencies
ticket_branch = create_author_create_curation_ticket_task
(
ticket_branch
>> close_author_create_user_ticket_task
>> set_workflow_status_to_completed_task
)
(ticket_branch >> close_author_create_user_ticket_task >> complete_task)

no_ticket_branch = combine_ticket_and_no_ticket_task
(
no_ticket_branch
>> close_author_create_user_ticket_task
>> set_workflow_status_to_completed_task
)
(no_ticket_branch >> close_author_create_user_ticket_task >> complete_task)

author_check_approval_branch_task >> [ticket_branch, no_ticket_branch]
(
Expand Down
11 changes: 10 additions & 1 deletion workflows/dags/author/author_create/author_create_rejected.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

from airflow.decorators import dag, task
from airflow.models.param import Param

# from .shared_tasks
from author.author_create.shared_tasks import create_decision_on_curation_choice
from hooks.backoffice.workflow_management_hook import AUTHORS, WorkflowManagementHook
from hooks.backoffice.workflow_ticket_management_hook import (
WorkflowTicketManagementHook,
Expand Down Expand Up @@ -67,9 +70,15 @@ def set_workflow_status_to_running(**context):
set_status_to_running_task = set_workflow_status_to_running()
close_ticket_task = close_author_create_user_ticket()
set_status_completed_task = set_author_create_workflow_status_to_completed()
create_decision_on_curation_choice_task = create_decision_on_curation_choice()

# task dependencies
set_status_to_running_task >> close_ticket_task >> set_status_completed_task
(
set_status_to_running_task
>> close_ticket_task
>> set_status_completed_task
>> create_decision_on_curation_choice_task
)


author_create_rejected_dag()
16 changes: 16 additions & 0 deletions workflows/dags/author/author_create/shared_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from airflow.decorators import task
from hooks.backoffice.base import BackofficeHook


@task()
def create_decision_on_curation_choice(**context):
print("create_decision_on_curation_choice")
print(context["params"])

data = {
"user_id": context["params"]["workflow_id"],
"action": context["params"]["workflow_id"],
"workflow_id": context["params"]["workflow_id"],
}

BackofficeHook().request(method="POST", data=data, endpoint="api/decisions/")
8 changes: 8 additions & 0 deletions workflows/plugins/hooks/backoffice/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,11 @@ def run(
prepped_request = session.prepare_request(req)
self.log.info("Sending '%s' to url: %s", method, url)
return self.run_and_check(session, prepped_request, extra_options)

def request(self, method, data, endpoint):
return self.run_with_advanced_retry(
_retry_args=self.tenacity_retry_kwargs,
method=method,
data=data,
endpoint=endpoint,
)
38 changes: 38 additions & 0 deletions workflows/plugins/hooks/backoffice/decision_management_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from hooks.backoffice.base import BackofficeHook
from requests import Response


class WorkflowTicketManagementHook(BackofficeHook):
"""
A hook to update the status of a workflow in the backoffice system.
:param method: The HTTP method to use for the request (default: "GET").
:type method: str
:param http_conn_id: The ID of the HTTP connection to use (
default: "backoffice_conn").
:type http_conn_id: str
"""

def __init__(
self,
method: str = "GET",
http_conn_id: str = "backoffice_conn",
headers: dict = None,
) -> None:
super().__init__(method, http_conn_id, headers)
self.endpoint = "api/decision/"

def create_decision_entry(
self, workflow_id: str, user_id: str, action: str
) -> Response:
data = {
"user_id": user_id,
"action": action,
"workflow_id": workflow_id,
}
return self.run_with_advanced_retry(
_retry_args=self.tenacity_retry_kwargs,
method="POST",
data=data,
endpoint=self.endpoint,
)

0 comments on commit 6a6bfc2

Please sign in to comment.