diff --git a/django/api/admin.py b/django/api/admin.py index 004e5bea..9b7faf2d 100644 --- a/django/api/admin.py +++ b/django/api/admin.py @@ -7,6 +7,7 @@ CancellableGoElectricRebateApplication, DriverLicenceEditableGoElectricRebateApplication, ChangeRedeemedGoElectricRebateApplication, + ExpiredGoElectricRebateApplication, ) from .models.household_member import HouseholdMember from .models.go_electric_rebate import GoElectricRebate @@ -15,11 +16,18 @@ from . import messages_custom from django.db.models import Q from django.db import transaction -from api.services.ncda import delete_rebate, update_rebate +from api.services.ncda import ( + delete_rebate, + update_rebate, + get_rebate_by_drivers_licence, + notify, +) from django_q.tasks import async_task from api.services.go_electric_rebate_application import ( equivalent_drivers_licence_number_found, ) +from api.model_forms.extend_expired_application import ExtendExpiryForm +from datetime import date, timedelta class ITVRModelAdmin(admin.ModelAdmin): @@ -440,7 +448,7 @@ def edit_drivers_licence(self, request, object_id, form_url, extra_context): @admin.register(ChangeRedeemedGoElectricRebateApplication) -class ChangeRedeemedGoElectricRebateApplication(ITVRModelAdmin): +class ChangeRedeemedGoElectricRebateApplicationAdmin(ITVRModelAdmin): search_fields = ["drivers_licence", "id", "status", "last_name"] exclude = ( "sin", @@ -497,3 +505,88 @@ def response_change(self, request, obj): if ncda_id is not None: update_rebate(ncda_id, {"Status": "Not-Redeemed"}) return ret + + +@admin.register(ExpiredGoElectricRebateApplication) +class ExpiredGoElectricRebateApplicationAdmin(ITVRModelAdmin): + form = ExtendExpiryForm + search_fields = ["drivers_licence", "id", "last_name"] + exclude = ( + "sin", + "doc1", + "doc2", + "user", + "spouse_email", + "status", + "address", + "city", + "postal_code", + "application_type", + "doc1_tag", + "doc2_tag", + "consent_personal", + "consent_tax", + "reason_for_decline", + ) + readonly_fields = ( + "id", + "last_name", + "first_name", + "middle_names", + "status", + "email", + "user_is_bcsc", + "drivers_licence", + "date_of_birth", + "tax_year", + "is_legacy", + "confirmation_email_success", + "spouse_email_success", + "created", + "approved_on", + "not_approved_on", + ) + + def get_queryset(self, request): + return GoElectricRebateApplication.objects.filter( + status=GoElectricRebateApplication.Status.EXPIRED + ) + + def response_change(self, request, obj): + ret = super().response_change(request, obj) + if "extend_expiry_date" in request.POST: + drivers_licence = obj.drivers_licence + rebate_exists = GoElectricRebate.objects.filter( + drivers_licence=drivers_licence + ).exists() + if rebate_exists is False: + ncda_rebate = get_rebate_by_drivers_licence(drivers_licence, ["Title"]) + if ncda_rebate is None: + obj.status = GoElectricRebateApplication.Status.APPROVED + obj.save(update_fields=["status"]) + rebate_amount = request.POST.get("rebate_amount") + last_name = obj.last_name + expiry_date = date.today() + timedelta(days=30) + ncda_data = notify( + drivers_licence, + last_name, + expiry_date.strftime("%m/%d/%Y"), + rebate_amount, + obj.id, + ) + ncda_id = ncda_data["d"]["ID"] + rebate = GoElectricRebate( + application=obj, + drivers_licence=drivers_licence, + last_name=last_name, + expiry_date=expiry_date, + rebate_max_amount=rebate_amount, + redeemed=False, + ncda_id=ncda_id, + ) + rebate.save() + else: + raise Exception("There exists an associated NCDA rebate!") + else: + raise Exception("There exists an associated Go Elecric Rebate!") + return ret diff --git a/django/api/migrations/0021_expiredgoelectricrebateapplication.py b/django/api/migrations/0021_expiredgoelectricrebateapplication.py new file mode 100644 index 00000000..467099c4 --- /dev/null +++ b/django/api/migrations/0021_expiredgoelectricrebateapplication.py @@ -0,0 +1,25 @@ +# Generated by Django 4.0.9 on 2024-06-03 17:31 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0020_alter_goelectricrebateapplication_drivers_licence'), + ] + + operations = [ + migrations.CreateModel( + name='ExpiredGoElectricRebateApplication', + fields=[ + ], + options={ + 'ordering': ['-modified'], + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('api.goelectricrebateapplication',), + ), + ] diff --git a/django/api/model_forms/extend_expired_application.py b/django/api/model_forms/extend_expired_application.py new file mode 100644 index 00000000..77d15458 --- /dev/null +++ b/django/api/model_forms/extend_expired_application.py @@ -0,0 +1,17 @@ +from django import forms +from api.models.go_electric_rebate_application import ExpiredGoElectricRebateApplication +from api.constants import ONE_THOUSAND_REBATE, TWO_THOUSAND_REBATE, FOUR_THOUSAND_REBATE + + +class ExtendExpiryForm(forms.ModelForm): + rebate_amount = forms.ChoiceField( + choices=[ + (ONE_THOUSAND_REBATE.ZEV_MAX.value, ONE_THOUSAND_REBATE.ZEV_MAX.value), + (TWO_THOUSAND_REBATE.ZEV_MAX.value, TWO_THOUSAND_REBATE.ZEV_MAX.value), + (FOUR_THOUSAND_REBATE.ZEV_MAX.value, FOUR_THOUSAND_REBATE.ZEV_MAX.value), + ] + ) + + class Meta: + model = ExpiredGoElectricRebateApplication + fields = "__all__" diff --git a/django/api/models/go_electric_rebate_application.py b/django/api/models/go_electric_rebate_application.py index 6d4fbb2e..1ee63e24 100644 --- a/django/api/models/go_electric_rebate_application.py +++ b/django/api/models/go_electric_rebate_application.py @@ -280,6 +280,7 @@ class Meta: def admin_label(cls): return "Edit DL#'s" + class ChangeRedeemedGoElectricRebateApplication(GoElectricRebateApplication): class Meta: proxy = True @@ -289,3 +290,12 @@ class Meta: def admin_label(cls): return "Change Redeemed Status" + +class ExpiredGoElectricRebateApplication(GoElectricRebateApplication): + class Meta: + proxy = True + ordering = ["-modified"] + + @classproperty + def admin_label(cls): + return "Extend Expiry Dates" diff --git a/django/api/services/ncda.py b/django/api/services/ncda.py index ccf9723a..1a80e90b 100644 --- a/django/api/services/ncda.py +++ b/django/api/services/ncda.py @@ -248,7 +248,7 @@ def delete_rebate(ncda_id): ncda_rs.raise_for_status() -def get_rebate(ncda_id, fields): +def get_rebates(filter, fields): api_endpoint = settings.NCDA_SHAREPOINT_URL access_token = get_ncda_service_token() @@ -260,11 +260,12 @@ def get_rebate(ncda_id, fields): url = api_endpoint + "/lists/getbytitle('ITVREligibility')/items" - select_fields = ",".join(fields) payload = { - "$select": select_fields, - "$filter": "(Id eq %s)" % ncda_id, + "$filter": filter, } + if fields: + payload["$select"] = ",".join(fields) + ncda_rs = requests.get(url, headers=headers, params=payload, verify=True) ncda_rs.raise_for_status() data = ncda_rs.json() @@ -273,6 +274,22 @@ def get_rebate(ncda_id, fields): return items +def get_rebate_by_id(ncda_id, fields=[]): + filter = "(Id eq %s)" % ncda_id + rebates = get_rebates(filter, fields) + if len(rebates) >= 1: + return rebates[0] + return None + + +def get_rebate_by_drivers_licence(drivers_licence, fields=[]): + filter = "(Title eq '%s')" % drivers_licence + rebates = get_rebates(filter, fields) + if len(rebates) >= 1: + return rebates[0] + return None + + def update_rebate(ncda_id, updated_fields): api_endpoint = settings.NCDA_SHAREPOINT_URL access_token = get_ncda_service_token() diff --git a/django/api/tasks.py b/django/api/tasks.py index f04ba7f2..c0404df8 100644 --- a/django/api/tasks.py +++ b/django/api/tasks.py @@ -14,7 +14,7 @@ from api.services.ncda import ( notify, get_rebates_redeemed_since, - get_rebate, + get_rebate_by_id, delete_rebate, ) from api.constants import ( @@ -559,8 +559,8 @@ def expire_expired_applications(max_number_of_rebates=50, days_offset=15): @transaction.atomic def expire_rebate(rebate): ncda_id = rebate.ncda_id - ncda_rebates = get_rebate(ncda_id, ["Status"]) - if len(ncda_rebates) == 1 and ncda_rebates[0]["Status"] == "Not-Redeemed": + ncda_rebate = get_rebate_by_id(ncda_id, ["Status"]) + if ncda_rebate is not None and ncda_rebate["Status"] == "Not-Redeemed": application = rebate.application if application: application.status = GoElectricRebateApplication.Status.EXPIRED diff --git a/django/api/templates/admin/api/expiredgoelectricrebateapplication/change_form.html b/django/api/templates/admin/api/expiredgoelectricrebateapplication/change_form.html new file mode 100644 index 00000000..942aaa5d --- /dev/null +++ b/django/api/templates/admin/api/expiredgoelectricrebateapplication/change_form.html @@ -0,0 +1,4 @@ +{% extends "admin/api/change_form.html" %} {% load i18n admin_urls jazzmin %} {% +get_jazzmin_ui_tweaks as jazzmin_ui %} + +{% block itvr_subheader %}{% endblock %} \ No newline at end of file diff --git a/django/api/templates/admin/api/expiredgoelectricrebateapplication/change_list.html b/django/api/templates/admin/api/expiredgoelectricrebateapplication/change_list.html new file mode 100644 index 00000000..d34e5945 --- /dev/null +++ b/django/api/templates/admin/api/expiredgoelectricrebateapplication/change_list.html @@ -0,0 +1,5 @@ +{% extends "admin/api/change_list.html" %} +{% load i18n admin_urls static admin_list jazzmin %} {% + +{% block content_title %} Extend Expiry Dates {% endblock %} +{% block itvr_subtitle %} Extend Expiry Dates {% endblock %} \ No newline at end of file diff --git a/django/api/templates/admin/api/expiredgoelectricrebateapplication/submit_line.html b/django/api/templates/admin/api/expiredgoelectricrebateapplication/submit_line.html new file mode 100644 index 00000000..5ba1f1c4 --- /dev/null +++ b/django/api/templates/admin/api/expiredgoelectricrebateapplication/submit_line.html @@ -0,0 +1,26 @@ +{% extends "admin/submit_line.html" %} +{% load i18n admin_urls jazzmin %} +{% get_jazzmin_ui_tweaks as jazzmin_ui %} +{% load static %} +{% block submit-row %} + +