diff --git a/example_project/settings.py b/example_project/settings.py index 4998bd3..69243f3 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -110,12 +110,8 @@ def abspath(*args): "prefill": os.environ.get("STRIPE_PREFILL", True), "remember_me": os.environ.get("STRIPE_REMEMBER_ME", False), "locale": os.environ.get("STRIPE_LOCALE", "auto"), - "enable_billing_address": os.environ.get( - "STRIPE_ENABLE_BILLING_ADDRESS", False - ), - "enable_shipping_address": os.environ.get( - "STRIPE_ENABLE_SHIPPING_ADDRESS", False - ), + "enable_billing_address": os.environ.get("STRIPE_ENABLE_BILLING_ADDRESS", False), + "enable_shipping_address": os.environ.get("STRIPE_ENABLE_SHIPPING_ADDRESS", False), }, }, }, diff --git a/payment/admin.py b/payment/admin.py index 67fa04b..b72f96f 100644 --- a/payment/admin.py +++ b/payment/admin.py @@ -1,11 +1,20 @@ +from django.conf.urls import url from django.contrib import admin +from django.forms import forms +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.html import format_html from django.utils.translation import ugettext_lazy as _ +from djmoney.forms import MoneyField from import_export.admin import ExportMixin from import_export.formats import base_formats from moneyed.localization import format_money from .export import PaymentResource -from .models import Payment, Transaction +from .models import Payment +from .models import Transaction +from .utils import gateway_refund ############################################################## @@ -68,6 +77,35 @@ def has_module_permission(self, request): ############################################################## # Payments + +class RefundPaymentForm(forms.Form): + amount = MoneyField(min_value=0) + + +def refund_payment_form(request, payment_id): + payment = get_object_or_404(Payment, pk=payment_id) + if request.method == 'POST': + form = RefundPaymentForm(request.POST) + if form.is_valid(): + gateway_refund( + payment=payment, + amount=form.cleaned_data['amount']) + # As confirmation we take the user to the payment page + return HttpResponseRedirect(reverse('admin:payment_payment_change', args=[payment_id])) + else: + form = RefundPaymentForm(initial={'amount': payment.captured_amount}) + + return render( + request, + 'admin/payment/form.html', + { + 'title': 'Refund to {}, for payment with total: {}'.format(payment.gateway, payment.total), + 'form': form, + 'opts': Payment._meta, # Used to setup the navigation / breadcrumbs of the page + } + ) + + @admin.register(Payment) class PaymentAdmin(ExportMixin, admin.ModelAdmin): date_hierarchy = 'created' @@ -77,6 +115,7 @@ class PaymentAdmin(ExportMixin, admin.ModelAdmin): 'customer_email'] search_fields = ['customer_email', 'token', 'total', 'id'] + readonly_fields = ['created', 'modified', 'refund_button'] inlines = [TransactionInline] resource_class = PaymentResource @@ -92,3 +131,24 @@ def formatted_captured_amount(self, obj): return format_money(obj.captured_amount) formatted_captured_amount.short_description = _('captured amount') # type: ignore + + def get_urls(self): + urls = super().get_urls() + my_urls = [ + url( + r'^(?P[0-9a-f-]+)/refund/$', + self.admin_site.admin_view(refund_payment_form), + name='payment_refund', + ), + ] + return my_urls + urls + + def refund_button(self, payment): + if payment.can_refund(): + return format_html('{}', + reverse('admin:payment_refund', args=[payment.pk]), + _('Refund')) + else: + return '-' + + refund_button.short_description = _('Refund') # type: ignore diff --git a/payment/locale/fr/LC_MESSAGES/django.mo b/payment/locale/fr/LC_MESSAGES/django.mo index a542755..e11dc14 100644 Binary files a/payment/locale/fr/LC_MESSAGES/django.mo and b/payment/locale/fr/LC_MESSAGES/django.mo differ diff --git a/payment/locale/fr/LC_MESSAGES/django.po b/payment/locale/fr/LC_MESSAGES/django.po index 009fd4b..8833941 100644 --- a/payment/locale/fr/LC_MESSAGES/django.po +++ b/payment/locale/fr/LC_MESSAGES/django.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-29 07:50-0500\n" -"PO-Revision-Date: 2019-07-29 12:51+0000\n" +"POT-Creation-Date: 2019-09-12 09:24-0500\n" +"PO-Revision-Date: 2019-09-12 14:25+0000\n" "Last-Translator: b' '\n" "Language-Team: LANGUAGE \n" "Language: \n" @@ -69,26 +69,32 @@ msgctxt "payment status" msgid "Fully refunded" msgstr "Remboursé" -#: admin.py:17 models.py:228 +#: admin.py:28 models.py:168 msgid "amount" msgstr "montant" -#: admin.py:25 models.py:97 models.py:222 +#: admin.py:36 models.py:37 models.py:162 msgid "created" msgstr "créé" -#: admin.py:33 models.py:98 +#: admin.py:44 models.py:38 msgid "modified" msgstr "modifié" -#: admin.py:143 models.py:102 +#: admin.py:127 models.py:42 msgid "total" msgstr "total" -#: admin.py:149 models.py:103 +#: admin.py:133 models.py:43 msgid "captured amount" msgstr "montant capturé" +#: admin.py:150 admin.py:154 +#| msgctxt "transaction kind" +#| msgid "Refund" +msgid "Refund" +msgstr "Remboursement" + #: apps.py:7 msgid "Payment" msgstr "Paiement" @@ -121,88 +127,87 @@ msgctxt "Stripe payment gateway description" msgid "Total payment" msgstr "Paiement total" -#: models.py:95 +#: models.py:35 msgid "gateway" msgstr "passerelle" -#: models.py:96 +#: models.py:36 msgid "is_active" msgstr "actif?" -#: models.py:99 +#: models.py:39 msgid "charge status" msgstr "Status paiement" -#: models.py:101 models.py:225 +#: models.py:41 models.py:165 msgid "token" msgstr "jeton" -#: models.py:105 +#: models.py:45 msgid "cc first digits" msgstr "cc premiers chiffres" -#: models.py:106 +#: models.py:46 msgid "cc last digits" msgstr "cc derniers chiffres" -#: models.py:107 +#: models.py:47 msgid "cc brand" msgstr "cc marque" -#: models.py:108 +#: models.py:48 msgid "cc exp month" msgstr "cc mois d'expiration" -#: models.py:111 +#: models.py:51 msgid "cc exp year" msgstr "cc année d'expiration" -#: models.py:114 +#: models.py:54 msgid "customer email" msgstr "email client" -#: models.py:116 +#: models.py:56 msgid "customer ip address" msgstr "adresse ip client" -#: models.py:117 +#: models.py:57 msgid "extra data" msgstr "données supplémentaires" -#: models.py:120 models.py:224 +#: models.py:60 models.py:164 msgid "payment" msgstr "paiement" -#: models.py:121 +#: models.py:61 msgid "payments" msgstr "paiements" -#: models.py:125 -#, fuzzy +#: models.py:65 #| msgid "Payment %s (%s)" msgid "Payment {} ({})" msgstr "Paiement {} ({})" -#: models.py:226 +#: models.py:166 msgid "kind" msgstr "type" -#: models.py:227 +#: models.py:167 msgid "is success" msgstr "succès?" -#: models.py:229 +#: models.py:169 msgid "error" msgstr "erreur" -#: models.py:230 +#: models.py:170 msgid "gateway response" msgstr "réponse passerelle" -#: models.py:233 +#: models.py:173 msgid "transaction" msgstr "transaction" -#: models.py:234 +#: models.py:174 msgid "transactions" msgstr "transactions" diff --git a/payment/templates/admin/payment/form.html b/payment/templates/admin/payment/form.html new file mode 100644 index 0000000..c75afde --- /dev/null +++ b/payment/templates/admin/payment/form.html @@ -0,0 +1,22 @@ +{% extends 'admin/base_site.html' %} + +{% load i18n %} + +{% if not is_popup %} +{% block breadcrumbs %} + +{% endblock %} +{% endif %} + +{% block content %} +
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} \ No newline at end of file diff --git a/setup.py b/setup.py index 0b9b212..78031b1 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,11 @@ 'payment.migrations', ], package_data={ - 'payment': ['locale/*/LC_MESSAGES/*.*', ]}, + 'payment': [ + 'locale/*/LC_MESSAGES/*.*', + 'templates/admin/payment/*.html', + ] + }, install_requires=[ 'Django>=2.2,<2.3', 'django-money',