Skip to content

Commit

Permalink
feat: payment notification
Browse files Browse the repository at this point in the history
This is a improved version of #72
  • Loading branch information
felipemontoya authored and andrey-canon committed Oct 3, 2023
1 parent e145f56 commit 4022c03
Show file tree
Hide file tree
Showing 17 changed files with 701 additions and 2 deletions.
1 change: 1 addition & 0 deletions eox_nelp/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
from eox_nelp.admin.course_creators import * # noqa: F401
from eox_nelp.course_experience.admin import * # noqa: F401
from eox_nelp.notifications.admin import * # noqa: F401
from eox_nelp.payment_notifications.admin import * # noqa: F401
7 changes: 7 additions & 0 deletions eox_nelp/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ class EoxNelpConfig(AppConfig):
'dispatch_uid': 'enrollment_publisher_receiver',
'sender_path': 'common.djangoapps.student.models.CourseEnrollment',
},
{
'receiver_func_name': 'update_payment_notifications',
'signal_path': 'django.db.models.signals.post_save',
'dispatch_uid': 'update_payment_notifications_receiver',
'sender_path': 'common.djangoapps.student.models.CourseEnrollment',
},
],
},
},
Expand All @@ -69,6 +75,7 @@ def ready(self):
# pylint: disable=unused-import, import-error, import-outside-toplevel
# This is required in order to register the receiver inside handlers module.
from cms.djangoapps.contentstore.signals import handlers # noqa: F401

run_init_pipeline()


Expand Down
6 changes: 4 additions & 2 deletions eox_nelp/init_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@ def set_mako_templates():
# and therefore the settings has not been set yet
from eox_nelp.course_experience.frontend import templates as course_experience_templates
from eox_nelp.edxapp_wrapper.edxmako import edxmako
from eox_nelp.payment_notifications import templates as payment_notifications_templates
from eox_nelp.stats import templates as stats_templates

templates_modules_to_include = [
module_templates_to_include = [
stats_templates,
course_experience_templates,
payment_notifications_templates,
]

for module in templates_modules_to_include:
for module in module_templates_to_include:
path_to_templates = os.path.dirname(module.__file__)

if path_to_templates not in edxmako.LOOKUP['main'].directories:
Expand Down
56 changes: 56 additions & 0 deletions eox_nelp/migrations/0005_paymentnotification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 3.2.13 on 2023-07-26 15:21

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('eox_nelp', '0004_feedback_public_default_to_false'),
]

operations = [
migrations.CreateModel(
name='PaymentNotification',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('cdtrans_lms_user_id', models.IntegerField(blank=True, db_index=True, null=True)),
('cdtrans_sku', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_username', models.CharField(blank=True, max_length=200, null=True)),
('cdtrans_email', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_amount', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_course_id', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_enrollment_id', models.IntegerField(blank=True, null=True)),
('cdtrans_mode', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_cert_status', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_date', models.DateTimeField(blank=True, null=True)),
('cdtrans_response_id', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_status', models.CharField(blank=True, max_length=100, null=True)),
('cdtrans_ecom_order_id', models.IntegerField(blank=True, null=True)),
('cdtrans_ecom_payment_reponse_id', models.IntegerField(blank=True, null=True)),
('cdtrans_extra_data_1', models.CharField(blank=True, max_length=1000, null=True)),
('cdtrans_extra_data_2', models.CharField(blank=True, max_length=1000, null=True)),
('cdtrans_extra_data_3', models.CharField(blank=True, max_length=1000, null=True)),
('cdtrans_extra_data_4', models.TextField(blank=True, null=True)),
('show_msg_case0', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('show_msg_case1', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('show_msg_case2', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('show_trans_info', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('show_msg_custom', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('custom_msg', models.TextField(blank=True, help_text='Not ready', null=True)),
('call_to_action_1_msg', models.CharField(blank=True, help_text='Not ready', max_length=1000, null=True)),
('call_to_action_2_msg', models.CharField(blank=True, help_text='Not ready', max_length=1000, null=True)),
('call_to_action_3_msg', models.CharField(blank=True, help_text='Not ready', max_length=1000, null=True)),
('call_to_action_1_url', models.CharField(blank=True, help_text='Not ready', max_length=1000, null=True)),
('call_to_action_2_url', models.CharField(blank=True, help_text='Not ready', max_length=1000, null=True)),
('call_to_action_3_url', models.CharField(blank=True, help_text='Not ready', max_length=1000, null=True)),
('redirect_from_dashboard', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('redirect_from_course', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('redirect_from_certificate', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('redirect_from_everywhere', models.BooleanField(blank=True, help_text='Not ready', null=True)),
('internal_status', models.CharField(choices=[('case_0', 'case_0'), ('case_1', 'case_1'), ('case_2', 'case_2'), ('pending_manual_eval', 'pending_manual_eval'), ('other_case', 'other_case'), ('ignore', 'ignore'), ('resolution_by_case_0', 'resolution_by_case_0'), ('resolution_by_case_1', 'resolution_by_case_1'), ('resolution_by_case_2', 'resolution_by_case_2'), ('resolution_other', 'resolution_other')], default='case_0', max_length=30)),
('internal_notes', models.CharField(blank=True, max_length=2000, null=True)),
('internal_view_count', models.IntegerField(default=0)),
],
),
]
23 changes: 23 additions & 0 deletions eox_nelp/migrations/0006_auto_20230726_1707.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.13 on 2023-07-26 17:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('eox_nelp', '0005_paymentnotification'),
]

operations = [
migrations.AddField(
model_name='paymentnotification',
name='cdtrans_card_last_4_digits',
field=models.CharField(blank=True, max_length=10, null=True),
),
migrations.AlterField(
model_name='paymentnotification',
name='internal_notes',
field=models.TextField(blank=True, max_length=2000, null=True),
),
]
Empty file.
108 changes: 108 additions & 0 deletions eox_nelp/payment_notifications/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""
Payment notifications admin file.
This module contains the admin configuration for the PaymentNotification model.
It defines the admin class PaymentNotificationAdmin, which specifies how the
PaymentNotification model is displayed and interacted with in the Django admin interface.
Attributes:
PaymentNotificationAdmin (admin.ModelAdmin): The admin class for PaymentNotification
that customizes the display and functionality of the admin interface for this model.
This admin class defines the list of fields to be displayed, search fields, and filters
for PaymentNotification objects. It also includes several methods for summarizing
user data, transaction data, and message cases, which are used for displaying information
in the admin interface.
Methods:
- user_summary(self, obj): Summarizes user data.
- transaction_summary(self, obj): Summarizes transaction data.
- msg_cases(self, obj): Shows message case state.
- redirections_state(self, obj): Shows redirections state.
"""
from django.contrib import admin

from eox_nelp.payment_notifications.models import PaymentNotification


class PaymentNotificationAdmin(admin.ModelAdmin):
"""Admin class for PaymentNotification."""

list_display = (
"user_summary",
"internal_status",
"cdtrans_amount",
"cdtrans_date",
"transaction_summary",
"msg_cases",
"redirections_state",
"internal_view_count",
)
search_fields = (
"cdtrans_lms_user_id",
"cdtrans_username",
"cdtrans_email",
"cdtrans_course_id",
"cdtrans_response_id",
"cdtrans_amount",
"cdtrans_course_id",
"internal_status",
"cdtrans_cert_status",
"cdtrans_enrollment_id",
"cdtrans_sku",
)
list_filter = (
"cdtrans_course_id",
"cdtrans_amount",
"internal_status",
"show_msg_case0",
"show_msg_case1",
"show_msg_case2",
"show_msg_custom",
"redirect_from_dashboard",
"redirect_from_course",
"redirect_from_certificate",
"redirect_from_everywhere",
)

def user_summary(self, obj):
"""Summaries user data"""
return f"""
lms_user_id: {obj.cdtrans_lms_user_id}
username: {obj.cdtrans_username}
email: {obj.cdtrans_email}
course_id: {obj.cdtrans_course_id}
enrollment_id: {obj.cdtrans_enrollment_id}
certificate_status: {obj.cdtrans_cert_status}
"""

def transaction_summary(self, obj):
"""Summaries transaction data"""
return f"""
sku: {obj.cdtrans_sku}
response_id: {obj.cdtrans_response_id}
status: {obj.cdtrans_status}
response_ id: {obj.cdtrans_response_id}
amount: {obj.cdtrans_amount}
date: {obj.cdtrans_date}
"""

def msg_cases(self, obj):
"""Show msg case state"""
return f"""
show_msg_case0: {obj.show_msg_case0}
show_msg_case1: {obj.show_msg_case1}
show_msg_case2: {obj.show_msg_case2}
"""

def redirections_state(self, obj):
"""Show redirections state"""
return f"""
redirect_from_dashboard: {obj.redirect_from_dashboard}
redirect_from_course: {obj.redirect_from_course}
redirect_from_certificate: {obj.redirect_from_certificate}
redirect_from_everywhere : {obj.redirect_from_everywhere}
"""


admin.site.register(PaymentNotification, PaymentNotificationAdmin)
20 changes: 20 additions & 0 deletions eox_nelp/payment_notifications/context_processor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
Get the payment notifications context.
This function is used to obtain the necessary context for payment notifications
and returns it as a dictionary.
Args:
request: The HttpRequest object representing the HTTP request.
Returns:
dict: A dictionary with the payment notifications context.
"""
from eox_nelp.payment_notifications.views import get_payment_notifications_context


def payments_notifications_context(request):
"""
This function works as a payment notification context
"""
return get_payment_notifications_context(request)
121 changes: 121 additions & 0 deletions eox_nelp/payment_notifications/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""
eox_nelp model for notifications
"""
import logging

from django.db import models

logger = logging.getLogger(__name__)


class PaymentNotification(models.Model):
"""
PaymentNotification model
"""
id = models.AutoField(primary_key=True)

# This data comes from the Payment transaction
cdtrans_lms_user_id = models.IntegerField(db_index=True, null=True, blank=True)

cdtrans_sku = models.CharField(max_length=100, null=True, blank=True)
cdtrans_username = models.CharField(max_length=200, null=True, blank=True)
cdtrans_email = models.CharField(max_length=100, null=True, blank=True)
cdtrans_amount = models.CharField(max_length=100, null=True, blank=True)
cdtrans_course_id = models.CharField(max_length=100, null=True, blank=True)
cdtrans_enrollment_id = models.IntegerField(null=True, blank=True)
cdtrans_mode = models.CharField(max_length=100, null=True, blank=True)
cdtrans_cert_status = models.CharField(max_length=100, null=True, blank=True)
cdtrans_date = models.DateTimeField(null=True, blank=True)
cdtrans_response_id = models.CharField(max_length=100, null=True, blank=True)
cdtrans_status = models.CharField(max_length=100, null=True, blank=True)
cdtrans_ecom_order_id = models.IntegerField(null=True, blank=True)
cdtrans_ecom_payment_reponse_id = models.IntegerField(null=True, blank=True)

cdtrans_card_last_4_digits = models.CharField(max_length=10, null=True, blank=True)

cdtrans_extra_data_1 = models.CharField(max_length=1000, null=True, blank=True)
cdtrans_extra_data_2 = models.CharField(max_length=1000, null=True, blank=True)
cdtrans_extra_data_3 = models.CharField(max_length=1000, null=True, blank=True)
cdtrans_extra_data_4 = models.TextField(null=True, blank=True)

# Control surface
show_msg_case0 = models.BooleanField(null=True, blank=True, help_text="Will show the case 0 msg to the user")
show_msg_case1 = models.BooleanField(null=True, blank=True, help_text="Will show the case 1 msg to the user")
show_msg_case2 = models.BooleanField(null=True, blank=True, help_text="Will show the case 2 msg to the user")

show_trans_info = models.BooleanField(
null=True,
blank=True,
help_text="Will show the transaction details to the user",
)

show_msg_custom = models.BooleanField(null=True, blank=True, help_text="Will show the following html to the user")
custom_msg = models.TextField(
null=True,
blank=True,
help_text='Use a "lang-ar" or "lang-en" class to select language',
)

call_to_action_1_msg = models.CharField(
max_length=1000,
null=True,
blank=True,
help_text="Name of the button for case 1",
)
call_to_action_2_msg = models.CharField(
max_length=1000,
null=True, blank=True,
help_text="Name of the button for case 2",
)
call_to_action_3_msg = models.CharField(
max_length=1000,
null=True,
blank=True,
help_text="Name of the button at the end of the message",
)

call_to_action_1_url = models.CharField(
max_length=1000,
null=True,
blank=True,
help_text="Link of the button for case 1",
)
call_to_action_2_url = models.CharField(
max_length=1000,
null=True,
blank=True,
help_text="Link of the button for case 2",
)
call_to_action_3_url = models.CharField(
max_length=1000,
null=True,
blank=True,
help_text="Link of the button at the end of the message",
)

redirect_from_dashboard = models.BooleanField(null=True, blank=True, help_text="Not ready")
redirect_from_course = models.BooleanField(null=True, blank=True, help_text="Not ready")
redirect_from_certificate = models.BooleanField(null=True, blank=True, help_text="Not ready")
redirect_from_everywhere = models.BooleanField(null=True, blank=True, help_text="Not ready")

# Dashboard control
INTERNAL_STATUS = [
("case_0", "case_0"),
("case_1", "case_1"),
("case_2", "case_2"),
("pending_manual_eval", "pending_manual_eval"),
("other_case", "other_case"),
("ignore", "ignore"),
("resolution_by_case_0", "resolution_by_case_0"),
("resolution_by_case_1", "resolution_by_case_1"),
("resolution_by_case_2", "resolution_by_case_2"),
("resolution_other", "resolution_other"),
]
internal_status = models.CharField(
max_length=30,
choices=INTERNAL_STATUS,
default='case_0',
)
internal_notes = models.TextField(max_length=2000, null=True, blank=True)

internal_view_count = models.IntegerField(default=0)
Empty file.
Loading

0 comments on commit 4022c03

Please sign in to comment.