diff --git a/comments/views.py b/comments/views.py index fc74cb4b5..716700f08 100644 --- a/comments/views.py +++ b/comments/views.py @@ -17,9 +17,15 @@ from comments.forms import AdminCommentForm, CommentFilterForm from comments.models import CannedResponse, CommentModeration +from moyapay.payments import MoyaPayModeratorPayout def update(request, comment_pk, action): + if CommentModeration.objects.get(id=comment_pk).state == CommentModeration.CommentModerationState.REJECTED: + user = request.user + comment = XtdComment.objects.get(pk=comment_pk) + MoyaPayModeratorPayout(user=user, comment=comment).process_payment() + get_comment_with_children_filter = Q(parent_id=comment_pk) | Q(pk=comment_pk) comments = XtdComment.objects.filter(get_comment_with_children_filter) comment_moderations = [] diff --git a/home/migrations/0051_auto_20230331_0922.py b/home/migrations/0051_auto_20230331_0922.py new file mode 100644 index 000000000..0cbbf5480 --- /dev/null +++ b/home/migrations/0051_auto_20230331_0922.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.14 on 2023-03-31 09:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0050_auto_20230213_1214'), + ] + + operations = [ + migrations.AlterField( + model_name='manifestsettings', + name='language', + field=models.CharField(choices=[('ar', 'Arabic'), ('bn', 'Bengali'), ('ny', 'Chichewa'), ('prs', 'Dari'), ('en', 'English'), ('fr', 'French'), ('hi', 'Hindi'), ('id', 'Indonesian'), ('kaa', 'Karakalpak'), ('km', 'Khmer'), ('rw', 'Kinyarwanda'), ('rn', 'Kirundi'), ('ku', 'Kurdish'), ('mg', 'Malagasy'), ('ne', 'Nepali'), ('nr', 'Ndebele'), ('ps', 'Pashto'), ('pt', 'Portuguese'), ('qu', 'Quechua'), ('ru', 'Russian'), ('sn', 'Shona'), ('si', 'Sinhala'), ('es', 'Spanish'), ('sw', 'Swahili'), ('tg', 'Tajik'), ('ta', 'Tamil'), ('ti', 'Tigrinya'), ('tr', 'Turkish'), ('uk', 'Ukraine'), ('ur', 'Urdu'), ('uz', 'Uzbek'), ('zu', 'Zulu'), ('xy', 'Testing')], default='en', help_text='Choose language', max_length=3, verbose_name='Language'), + ), + ] diff --git a/iogt/settings/base.py b/iogt/settings/base.py index c10a7aeae..6e87a9d87 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -40,6 +40,7 @@ 'messaging', 'common', 'notifications', + 'moyapay', 'django.contrib.humanize', 'wagtail_localize', 'wagtail_localize.locales', @@ -239,7 +240,7 @@ WAGTAIL_USER_EDIT_FORM = 'iogt_users.forms.WagtailAdminUserEditForm' WAGTAIL_USER_CREATION_FORM = 'iogt_users.forms.WagtailAdminUserCreateForm' -WAGTAIL_USER_CUSTOM_FIELDS = ['display_name', 'first_name', 'last_name', 'email', 'terms_accepted'] +WAGTAIL_USER_CUSTOM_FIELDS = ['display_name', 'first_name', 'last_name', 'email', 'terms_accepted', 'moyapay_username'] # Base URL to use when referring to full URLs within the Wagtail admin backend - # e.g. in notification emails. Don't include '/admin' or a trailing slash diff --git a/iogt/templates/wagtailusers/users/create.html b/iogt/templates/wagtailusers/users/create.html index e7976a7b6..ebfcbc932 100644 --- a/iogt/templates/wagtailusers/users/create.html +++ b/iogt/templates/wagtailusers/users/create.html @@ -6,6 +6,7 @@ {% endif %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.email %} {% block extra_fields %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.moyapay_username %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.display_name %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.first_name %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.last_name %} diff --git a/iogt/templates/wagtailusers/users/edit.html b/iogt/templates/wagtailusers/users/edit.html index 3c099849a..e0bbf050c 100644 --- a/iogt/templates/wagtailusers/users/edit.html +++ b/iogt/templates/wagtailusers/users/edit.html @@ -6,6 +6,7 @@ {% endif %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.email %} {% block extra_fields %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.moyapay_username %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.display_name %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.first_name %} {% include "wagtailadmin/shared/field_as_li.html" with field=form.last_name %} diff --git a/iogt_users/adapters.py b/iogt_users/adapters.py index 900c01879..9e69ce7d4 100644 --- a/iogt_users/adapters.py +++ b/iogt_users/adapters.py @@ -5,9 +5,10 @@ class AccountAdapter(DefaultAccountAdapter): def save_user(self, request, user, form, commit=True): user = super(AccountAdapter, self).save_user(request, user, form, commit) data = form.cleaned_data + user.moyapay_username = data.get('moyapay_username') user.display_name = data.get('display_name') or data.get('username') user.first_name = data.get('first_name') user.last_name = data.get('last_name') user.terms_accepted = data.get('terms_accepted', False) - user.save(update_fields=['display_name', 'first_name', 'last_name', 'terms_accepted']) + user.save(update_fields=['display_name', 'first_name', 'last_name', 'terms_accepted', 'moyapay_username']) return user diff --git a/iogt_users/forms.py b/iogt_users/forms.py index c38937b6c..448c393a5 100644 --- a/iogt_users/forms.py +++ b/iogt_users/forms.py @@ -76,7 +76,7 @@ class Meta: class WagtailAdminUserCreateForm(WagtailUserCreationForm): email = forms.EmailField(required=False, label='Email') - display_name = forms.CharField(required=False, label='Display Name') + moyapay_username = forms.CharField(required=False, label='MoyaPay Username') first_name = forms.CharField(required=False, label='First Name') last_name = forms.CharField(required=False, label='Last Name') terms_accepted = forms.BooleanField(label=_('I accept the Terms and Conditions.')) @@ -96,6 +96,7 @@ def clean_displayname(self): class WagtailAdminUserEditForm(WagtailUserEditForm): email = forms.EmailField(required=False, label='Email') + moyapay_username = forms.CharField(required=False, label='MoyaPay Username') display_name = forms.CharField(required=False, label='Display Name') first_name = forms.CharField(required=False, label='First Name') last_name = forms.CharField(required=False, label='Last Name') diff --git a/iogt_users/migrations/0006_user_moyapay_username.py b/iogt_users/migrations/0006_user_moyapay_username.py new file mode 100644 index 000000000..c6c40d1b3 --- /dev/null +++ b/iogt_users/migrations/0006_user_moyapay_username.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.14 on 2023-03-31 09:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('iogt_users', '0005_auto_20220120_0813'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='moyapay_username', + field=models.CharField(blank=True, max_length=150, null=True, unique=True, verbose_name='MoyaPay username'), + ), + ] diff --git a/iogt_users/models.py b/iogt_users/models.py index c0c4695a9..03a4e49bb 100644 --- a/iogt_users/models.py +++ b/iogt_users/models.py @@ -17,6 +17,13 @@ class User(AbstractUser): display_name = models.CharField('display name', max_length=255, null=True, blank=True) email = models.EmailField('email address', null=True, blank=True) terms_accepted = models.BooleanField(default=False) + moyapay_username = models.CharField( + 'MoyaPay username', + max_length=150, + unique=True, + null=True, + blank=True, + ) has_filled_registration_survey = models.BooleanField(default=False) has_viewed_registration_survey = models.BooleanField(default=False) diff --git a/moyapay/__init__.py b/moyapay/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/moyapay/client.py b/moyapay/client.py new file mode 100644 index 000000000..b4a99af83 --- /dev/null +++ b/moyapay/client.py @@ -0,0 +1,43 @@ +from requests import Session, Request +from rest_framework import status + + +class MoyaPayClient: + BASE_URL = 'https://payments.api.dev.moyapayd.app' + customer_url = f'{BASE_URL}/customers' + merchant_url = f'{BASE_URL}/merchants' + merchant_token_url = f'{merchant_url}/tokens/validate' + merchant_wallet_url = f'{merchant_url}/wallet' + pay_customer_url = f'{customer_url}/pay' + + def __init__(self): + self.session = Session() + self.access_token = '' + + def _get_headers(self): + return { + 'Authorization': f'Bearer {self.access_token}', + 'Content-Type': 'application/json' + } + + def _get_validated_response(self, response): + if response.ok: + return response.json() + elif response.status_code == status.HTTP_401_UNAUTHORIZED: + raise Exception('Unauthorised - Invalid or no authentication token supplied') + else: + raise Exception(f'Something went wrong. Status: {response.status_code}') + + def _api_caller(self, request): + request = self.session.prepare_request(request) + response = self.session.send(request) + return self._get_validated_response(response) + + def authenticate(self): + request = Request(method='GET', url=self.merchant_token_url, headers=self._get_headers()) + self._api_caller(request) + + def get_merchant_balance(self): + request = Request(method='GET', url=self.merchant_wallet_url, headers=self._get_headers()) + return self._api_caller(request).get('balance') + diff --git a/moyapay/migrations/0001_initial.py b/moyapay/migrations/0001_initial.py new file mode 100644 index 000000000..3567aeb06 --- /dev/null +++ b/moyapay/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 3.1.14 on 2023-03-31 09:23 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='MoyaPayPayment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('amount', models.IntegerField()), + ('is_successful', models.BooleanField(default=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/moyapay/migrations/__init__.py b/moyapay/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/moyapay/models.py b/moyapay/models.py new file mode 100644 index 000000000..976abbf21 --- /dev/null +++ b/moyapay/models.py @@ -0,0 +1,12 @@ +from django.db import models +from iogt_users.models import User + + +class MoyaPayPayment(models.Model): + amount = models.IntegerField() + is_successful = models.BooleanField(default=True) + created_at = models.DateTimeField(auto_now_add=True) + user = models.ForeignKey(User, on_delete=models.CASCADE) + + def __str__(self): + return self.user.moyapay_username diff --git a/moyapay/payments.py b/moyapay/payments.py new file mode 100644 index 000000000..b6e007788 --- /dev/null +++ b/moyapay/payments.py @@ -0,0 +1,17 @@ +from django.utils import timezone + +from moyapay.client import MoyaPayClient +from moyapay.utils import can_process_payment + + +class MoyaPayModeratorPayout: + def __init__(self, user, comment): + self.user = user + self.comment = comment + self.amount = 50 + self.client = MoyaPayClient() + self.client.authenticate() + self.current_datetime = timezone.now().strftime("%Y-%m-%d %H:%M:%S") + + def process_payment(self): + can_process_payment(self.user, self.comment) diff --git a/moyapay/utils.py b/moyapay/utils.py new file mode 100644 index 000000000..3a20356a8 --- /dev/null +++ b/moyapay/utils.py @@ -0,0 +1,6 @@ +def can_process_payment(user, comment): + # if a moderator moderate his own comment + if comment.user == user: + return False + +