From 7ad1e269182ce7d30dc5aa96b9b0f2c9427dac95 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 30 Sep 2021 10:17:05 +0200 Subject: [PATCH 1/1] PZ: add basic operations. --- src/pz/admin.py | 43 ++++++++++++++++-- src/pz/bank.py | 40 +++++++++++++++++ src/pz/migrations/0002_auto_20210928_2116.py | 44 +++++++++++++++++++ .../migrations/0003_directdebit_iban_valid.py | 18 ++++++++ src/pz/migrations/0004_auto_20210929_1938.py | 18 ++++++++ src/pz/models.py | 22 ++++++++-- 6 files changed, 178 insertions(+), 7 deletions(-) create mode 100644 src/pz/bank.py create mode 100644 src/pz/migrations/0002_auto_20210928_2116.py create mode 100644 src/pz/migrations/0003_directdebit_iban_valid.py create mode 100644 src/pz/migrations/0004_auto_20210929_1938.py diff --git a/src/pz/admin.py b/src/pz/admin.py index 86779316c..0be845b19 100644 --- a/src/pz/admin.py +++ b/src/pz/admin.py @@ -1,5 +1,8 @@ from django.contrib import admin from django.utils.translation import gettext_lazy as _ +from django.utils.timezone import now +from fnpdjango.actions import export_as_csv_action +from . import bank from . import models @@ -8,7 +11,33 @@ admin.site.register(models.Campaign) @admin.register(models.DirectDebit) class DirectDebitAdmin(admin.ModelAdmin): - list_display = ['acquisition_date', 'amount', 'first_name', 'last_name'] + list_display = [ + 'payment_id', 'acquisition_date', + 'iban_valid', + 'bank_submission_date', + 'bank_acceptance_date', + 'amount', 'first_name', 'last_name', + ] + date_hierarchy = 'acquisition_date' + search_fields = [ + 'payment_id', 'first_name', 'last_name', 'street', 'building', 'town', 'flat', + 'phone', 'email', 'iban', + 'notes', + 'fundraiser_bill', + ] + list_filter = [ + 'iban_valid', + 'agree_fundraising', + 'agree_newsletter', + 'fundraiser', + 'campaign', + 'is_cancelled', + 'needs_redo', + 'optout', + 'amount', + 'sex', + 'is_consumer', + ] fieldsets = [ (None, { "fields": [ @@ -18,7 +47,7 @@ class DirectDebitAdmin(admin.ModelAdmin): ('town', 'flat'), ('postal_code', 'phone'), 'email', - 'iban', + ('iban', 'iban_valid', 'iban_warning'), 'payment_id', 'agree_contact', 'agree_fundraising', @@ -40,7 +69,15 @@ class DirectDebitAdmin(admin.ModelAdmin): ] }) ] - readonly_fields = ['agree_contact'] + readonly_fields = ['agree_contact', 'iban_valid', 'iban_warning'] + + def set_bank_submission(m,r,q): + q.update(bank_submission_date=now()) + actions = [ + bank.bank_export, + set_bank_submission, + export_as_csv_action(), + ] def agree_contact(self, obj): return _('obligatory') diff --git a/src/pz/bank.py b/src/pz/bank.py new file mode 100644 index 000000000..e1e91b770 --- /dev/null +++ b/src/pz/bank.py @@ -0,0 +1,40 @@ +import csv +from django.http import HttpResponse +from django.utils.translation import ugettext_lazy as _ + + +def bank_export(modeladmin, request, queryset): + response = HttpResponse(content_type='text/csv; charset=cp1250') + response['Content-Disposition'] = 'attachment; filename=export.csv' + writer = csv.writer(response) + writer.writerow([ + 'Identyfikator płatności (IDP)', + 'Nazwa Płatnika', + 'Adres Płatnika Ulica + numer domu', + 'Adres Płatnika kod+miejscowość', + 'Numer kierunkowy banku Płatnika', + 'Numer rachunku bankowego Płatnika', + 'Identyfikator Odbiorcy (NIP Odbiorcy)', + 'Osobowość prawna Płatnika (Osoba fizyczna)' + ]) + + # TODO: ansi encoding + + for obj in queryset: + street_addr = obj.street + if obj.building: + street_addr += ' ' + obj.building + if obj.flat: + street_addr += ' m. ' + obj.flat + street_addr = street_addr.strip() + writer.writerow([ + obj.payment_id, + ' '.join([obj.first_name, obj.last_name]).strip(), + street_addr, + ' '.join([obj.postal_code, obj.town]).strip(), + obj.iban[2:10], + obj.iban, + '9521877087', + 'OF' + ]) + return response diff --git a/src/pz/migrations/0002_auto_20210928_2116.py b/src/pz/migrations/0002_auto_20210928_2116.py new file mode 100644 index 000000000..c9c3061c0 --- /dev/null +++ b/src/pz/migrations/0002_auto_20210928_2116.py @@ -0,0 +1,44 @@ +# Generated by Django 2.2.19 on 2021-09-28 19:16 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('pz', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='directdebit', + name='acquisition_date', + field=models.DateField(blank=True, help_text='Date from the form', null=True, verbose_name='acquisition date'), + ), + migrations.AlterField( + model_name='directdebit', + name='agree_fundraising', + field=models.BooleanField(default=False, verbose_name='agree fundraising'), + ), + migrations.AlterField( + model_name='directdebit', + name='agree_newsletter', + field=models.BooleanField(default=False, verbose_name='agree newsletter'), + ), + migrations.AlterField( + model_name='directdebit', + name='amount', + field=models.IntegerField(blank=True, null=True, verbose_name='amount'), + ), + migrations.AlterField( + model_name='directdebit', + name='campaign', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='pz.Campaign', verbose_name='campaign'), + ), + migrations.AlterField( + model_name='directdebit', + name='fundraiser', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='pz.Fundraiser', verbose_name='fundraiser'), + ), + ] diff --git a/src/pz/migrations/0003_directdebit_iban_valid.py b/src/pz/migrations/0003_directdebit_iban_valid.py new file mode 100644 index 000000000..f3bd309f4 --- /dev/null +++ b/src/pz/migrations/0003_directdebit_iban_valid.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.19 on 2021-09-29 17:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pz', '0002_auto_20210928_2116'), + ] + + operations = [ + migrations.AddField( + model_name='directdebit', + name='iban_valid', + field=models.BooleanField(default=False, verbose_name='IBAN valid'), + ), + ] diff --git a/src/pz/migrations/0004_auto_20210929_1938.py b/src/pz/migrations/0004_auto_20210929_1938.py new file mode 100644 index 000000000..dc093a7e3 --- /dev/null +++ b/src/pz/migrations/0004_auto_20210929_1938.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.19 on 2021-09-29 17:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pz', '0003_directdebit_iban_valid'), + ] + + operations = [ + migrations.AlterField( + model_name='directdebit', + name='iban_valid', + field=models.NullBooleanField(default=False, verbose_name='IBAN valid'), + ), + ] diff --git a/src/pz/models.py b/src/pz/models.py index 3b52961f6..8b6db0e35 100644 --- a/src/pz/models.py +++ b/src/pz/models.py @@ -41,12 +41,13 @@ class DirectDebit(models.Model): phone = models.CharField(_('phone'), max_length=255, blank=True) email = models.CharField(_('e-mail'), max_length=255, blank=True) iban = models.CharField(_('IBAN'), max_length=255, blank=True) + iban_valid = models.NullBooleanField(_('IBAN valid'), default=False) is_consumer = models.BooleanField(_('is a consumer'), default=True) payment_id = models.CharField(_('payment identifier'), max_length=255, blank=True, unique=True) - agree_fundraising = models.BooleanField(_('agree fundraising')) - agree_newsletter = models.BooleanField(_('agree newsletter')) + agree_fundraising = models.BooleanField(_('agree fundraising'), default=False) + agree_newsletter = models.BooleanField(_('agree newsletter'), default=False) - acquisition_date = models.DateField(_('acquisition date'), help_text=_('Date from the form')) + acquisition_date = models.DateField(_('acquisition date'), help_text=_('Date from the form'), null=True, blank=True) submission_date = models.DateField(_('submission date'), null=True, blank=True, help_text=_('Date the fundaiser submitted the form')) bank_submission_date = models.DateField(_('bank submission date'), null=True, blank=True, help_text=_('Date when the form data is submitted to the bank')) bank_acceptance_date = models.DateField(_('bank accepted date'), null=True, blank=True, help_text=_('Date when bank accepted the form')) @@ -55,7 +56,7 @@ class DirectDebit(models.Model): fundraiser_commission = models.IntegerField(_('fundraiser commission'), null=True, blank=True) fundraiser_bill = models.CharField(_('fundaiser bill number'), max_length=255, blank=True) - amount = models.IntegerField(_('amount')) + amount = models.IntegerField(_('amount'), null=True, blank=True) notes = models.TextField(_('notes'), blank=True) @@ -69,6 +70,10 @@ class DirectDebit(models.Model): verbose_name = _('direct debit') verbose_name_plural = _('direct debits') + def save(self, **kwargs): + self.iban_valid = not self.iban_warning() if self.iban else None + super().save(**kwargs) + @classmethod def get_next_payment_id(cls): # Find the last object added. @@ -88,3 +93,12 @@ class DirectDebit(models.Model): break return payment_id + def iban_warning(self): + if not self.iban: + return 'No IBAN' + if len(self.iban) != 26: + return 'Bad IBAN length' + if int(self.iban[2:] + '2521' + self.iban[:2]) % 97 != 1: + return 'This IBAN number looks invalid' + return '' + iban_warning.short_description = '' -- 2.20.1