Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On-hold flag and celery task for applicationstatus updates. #253

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions request_a_govuk_domain/celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@
"task": "request_a_govuk_domain.request.tasks.check_email_failure_and_notify",
"schedule": crontab(minute="*/1"),
},
"application-status-checker": {
"task": "request_a_govuk_domain.request.tasks.check_application_status",
"schedule": crontab(hour="0"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to set the minute=0 otherwise it will run every minute at 0 hrs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to set the minute=0 otherwise it will run every minute at 0 hrs

hour=0, doing it once a day at midnight. But will ask Robert on Monday.

},
}
4 changes: 4 additions & 0 deletions request_a_govuk_domain/request/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
RegistryPublishedPerson,
Registrant,
Registrar,
TimeFlag,
)
from .model_admins import (
ApplicationAdmin,
Expand All @@ -19,6 +20,7 @@
RegistryPublishedPersonAdmin,
RegistrantAdmin,
RegistrarAdmin,
TimeFlagAdmin,
)


Expand All @@ -41,3 +43,5 @@
admin.site.register(Registrant, RegistrantAdmin)

admin.site.register(Registrar, RegistrarAdmin)

admin.site.register(TimeFlag, TimeFlagAdmin)
10 changes: 5 additions & 5 deletions request_a_govuk_domain/request/admin/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ def token(reference, domain_name: str) -> str:
return generated_token


def send_approval_or_rejection_email(request):
def send_approval_or_rejection_email(obj_id, action):
"""
Sends Approval/Rejection mail depending on the action ( approval/rejection ) in the request object

:param request: Request object
"""
application = Application.objects.get(pk=request.POST["obj_id"])
application = Application.objects.get(pk=obj_id)
registrar_email = application.registrar_person.email_address
reference = application.reference

Expand All @@ -101,10 +101,10 @@ def send_approval_or_rejection_email(request):
personalisation_dict = utils.personalisation(reference, registration_data)

# action would be either approval or rejection
approval_or_rejection = request.POST["action"]
# approval_or_rejection = request.POST["action"]

# If approval_or_rejection is approval, then add token to the personalisation
if approval_or_rejection == "approval":
if action == "approval":
personalisation_dict["token"] = token(
reference, registration_data["domain_name"]
)
Expand All @@ -114,7 +114,7 @@ def send_approval_or_rejection_email(request):
personalisation_dict["reason_for_rejection"] = review.reason

route_specific_email_template_name = utils.route_specific_email_template(
approval_or_rejection, registration_data
action, registration_data
)

utils.send_email(
Expand Down
12 changes: 12 additions & 0 deletions request_a_govuk_domain/request/admin/model_admins.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
RegistryPublishedPerson,
Registrant,
Registrar,
TimeFlag,
)
from .filters import (
StatusFilter,
Expand All @@ -31,6 +32,8 @@
from .forms import ReviewForm
from ..models.storage_util import s3_root_storage

MAX_OBJECTS = 1


class FileDownloadMixin:
"""
Expand Down Expand Up @@ -482,3 +485,12 @@ class RegistrantAdmin(admin.ModelAdmin):

class RegistrarAdmin(admin.ModelAdmin):
model = Registrar


class TimeFlagAdmin(admin.ModelAdmin):
model = TimeFlag

def has_add_permission(self, request):
if self.model.objects.count() >= MAX_OBJECTS:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be False for any user as we do not want to add more entries?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we will need a seed script?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we will need a seed script?

up for discussion with Robert/Jim/Max I guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be False for any user as we do not want to add more entries?

Done

return False
return super().has_add_permission(request)
4 changes: 3 additions & 1 deletion request_a_govuk_domain/request/admin/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ def post(self, request):
if "_confirm" in request.POST:
try:
# send email
send_approval_or_rejection_email(request)
send_approval_or_rejection_email(
request.POST["obj_id"], request.POST["action"]
)
self._set_application_status(request)
# To show the backend app user a message "[Approval/Rejection] email sent", get the type of
# action ( i.e. whether it is Approval or Rejection )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Generated by Django 4.2.13 on 2024-07-19 13:16

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("request", "0010_alter_application_ministerial_request_evidence_and_more"),
]

operations = [
migrations.CreateModel(
name="TimeFlag",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("on_hold_days", models.IntegerField(default=5)),
("to_close_days", models.IntegerField(default=60)),
],
),
migrations.AlterField(
model_name="application",
name="status",
field=models.CharField(
choices=[
("approved", "Approved"),
("rejected", "Rejected"),
("in_progress", "In Progress"),
("ready_2i", "Ready for 2i"),
("more_information", "More Information"),
("new", "New"),
("on_hold", "On-hold"),
("failed_confirmation_email", "Failed Confirmation Email"),
("failed_decision_email", "Failed Decision Email"),
],
default="new",
max_length=25,
),
),
]
2 changes: 2 additions & 0 deletions request_a_govuk_domain/request/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .organisation import Registrant, Registrar, RegistrantTypeChoices
from .person import Person, RegistryPublishedPerson, RegistrarPerson, RegistrantPerson
from .review import Review, ReviewFormGuidance
from .time_flags import TimeFlag

__all__ = [
"Application",
Expand All @@ -18,4 +19,5 @@
"RegistrarPerson",
"Review",
"ReviewFormGuidance",
"TimeFlag",
]
1 change: 1 addition & 0 deletions request_a_govuk_domain/request/models/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ApplicationStatus(models.TextChoices):
READY_2I = "ready_2i", _("Ready for 2i")
MORE_INFORMATION = "more_information", _("More Information")
NEW = "new", _("New")
ON_HOLD = "on_hold", _("On-hold")
FAILED_CONFIRMATION_EMAIL = "failed_confirmation_email", _(
"Failed Confirmation Email"
)
Expand Down
15 changes: 15 additions & 0 deletions request_a_govuk_domain/request/models/time_flags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.db import models


class TimeFlag(models.Model):
"""
An Admin can change the times on application status, defaults below
1. More Information more than 5 days change to On-hold.
2. On-hold more than 60 days change to Closed.
"""

on_hold_days = models.IntegerField(default=5)
to_close_days = models.IntegerField(default=60)

def __str__(self):
return "More Information and On-hold flags"
40 changes: 40 additions & 0 deletions request_a_govuk_domain/request/tasks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging
import re
from datetime import timedelta


from celery import shared_task
from django.db import transaction
Expand All @@ -8,11 +10,14 @@

from request_a_govuk_domain.request.constants import NOTIFY_TEMPLATE_ID_MAP

from .admin import email

from request_a_govuk_domain.request.models import (
Application,
ApplicationStatus,
NotificationResponseID,
TimeFlag,
Review,
)
from request_a_govuk_domain.request.utils import (
send_email,
Expand Down Expand Up @@ -162,3 +167,38 @@ def check_email_failure_and_notify() -> None:
# Delete the notification response id, as the necessary action after email failure email has been
# taken, so no need to track anymore
notification_response_id.delete()


@shared_task
@transaction.atomic
def check_application_status() -> None:
"""
Checks appliction status periodically
"""
time_flag = TimeFlag.objects.first()

if time_flag:
more_info_application = Application.objects.filter(status="more_information")
dhvander marked this conversation as resolved.
Show resolved Hide resolved
for application in more_info_application:
hold_diff = (
application.last_updated - timedelta(days=time_flag.on_hold_days)
).day
if hold_diff > time_flag.on_hold_days:
application.status = ApplicationStatus.ON_HOLD
application.save()

on_hold_application = Application.objects.filter(status="on_hold")
dhvander marked this conversation as resolved.
Show resolved Hide resolved
for application in on_hold_application:
close_diff = (
application.last_updated - timedelta(days=time_flag.to_close_days)
).day
if close_diff > time_flag.to_close_days:
application.status = ApplicationStatus.REJECTED
application.save()

# send an email
review = Review.objects.filter(application__id=application.id)
review.reason = "The application needed more information and time to responsed elapsed." # type: ignore
email.send_approval_or_rejection_email(application.id, "rejection")
else:
logger.info("No Application Status time flags exists. Please create them.")