Rebranding for leinelab

This commit is contained in:
lemoer 2024-12-29 04:21:21 +01:00
parent 676eb5de2f
commit 964ab5484a
19 changed files with 36 additions and 1396 deletions

View File

@ -1,8 +1,7 @@
byro-shackspace byro-leinelab
--------------- -------------
A plugin for byro_. It contains an importer for the A plugin for byro_.
old shackbureau_, as well as supporting code.
Development Development
=========== ===========
@ -11,4 +10,3 @@ Depending on your setup, you might need to add the python path environment varia
.. _byro: https://github.com/byro/byro .. _byro: https://github.com/byro/byro
.. _shackbureau: https://github.com/shackspace/shackbureau

10
byro_leinelab/__init__.py Normal file
View File

@ -0,0 +1,10 @@
from django.apps import AppConfig
class PluginConfig(AppConfig):
name = 'byro_leinelab'
class ByroPluginMeta:
name = 'leinelab'
default_app_config = 'byro_leinelab.PluginConfig'

View File

@ -10,9 +10,9 @@ from django.utils import timezone
class Command(BaseCommand): class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
from byro_shackspace.models import ShackProfile from byro_leinelab.models import ShackProfile
profiles = ShackProfile.objects.filter( profiles = LabProfile.objects.filter(
member__memberships__end__isnull=True, member__memberships__end__isnull=True,
is_keyholder=True, is_keyholder=True,
).order_by('member__number') ).order_by('member__number')

View File

@ -14,18 +14,12 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='ShackProfile', name='LabProfile',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('has_loeffelhardt_account', models.BooleanField(default=False)), ('is_werkstatt_member', models.BooleanField(default=False)),
('has_matomat_key', models.BooleanField(default=False)), ('has_allgemeine_sicherheitseinweisung', models.BooleanField(default=False)),
('has_metro_card', models.BooleanField(default=False)),
('has_safe_key', models.BooleanField(default=False)),
('has_selgros_card', models.BooleanField(default=False)),
('has_shack_iron_key', models.BooleanField(default=False)),
('has_snackomat_key', models.BooleanField(default=False)),
('is_keyholder', models.BooleanField(default=False)), ('is_keyholder', models.BooleanField(default=False)),
('signed_DSV', models.BooleanField(default=False)),
('ssh_public_key', models.TextField(blank=True, null=True)), ('ssh_public_key', models.TextField(blank=True, null=True)),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='profile_shack', to='members.Member')), ('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='profile_shack', to='members.Member')),
], ],

14
byro_leinelab/models.py Normal file
View File

@ -0,0 +1,14 @@
from annoying.fields import AutoOneToOneField
from django.db import models
class LabProfile(models.Model):
member = AutoOneToOneField(
to='members.Member',
on_delete=models.CASCADE,
related_name='profile_lab',
)
is_werkstatt_member = models.BooleanField(default=False)
has_allgemeine_sicherheitseinweisung = models.BooleanField(default=False)
is_keyholder = models.BooleanField(default=False)
ssh_public_key = models.TextField(null=True, blank=True)

View File

@ -1,15 +0,0 @@
from django.apps import AppConfig
class PluginConfig(AppConfig):
name = 'byro_shackspace'
class ByroPluginMeta:
name = 'shackspace'
def ready(self):
from . import utils # noqa
from . import signals # noqa
default_app_config = 'byro_shackspace.PluginConfig'

View File

@ -1,189 +0,0 @@
import json
from datetime import datetime, time, timedelta
from decimal import Decimal
import pytz
from byro_shackspace.models import ShackProfile
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils.dateparse import parse_date
from byro.bookkeeping.models import (
Account, AccountCategory, RealTransaction,
TransactionChannel, VirtualTransaction,
)
from byro.members.models import Member, Membership
TIMEZONE = pytz.timezone('Europe/Berlin')
def localize(date):
if date:
return TIMEZONE.localize(datetime.combine(date, time.min))
def _import_sepa(member_data, member):
sepa_keys = [
'iban', 'mandate_reason', 'zip_code', 'country',
'city', 'bic', 'address', 'fullname', 'issue_date',
'institute', 'mandate_reference',
]
for key in sepa_keys:
setattr(member.profile_sepa, key, member_data.get(f'sepa__{key}'))
member.profile_sepa.save()
def _get_main_accounts():
fee_account, _ = Account.objects.get_or_create(
account_category=AccountCategory.MEMBER_FEES,
)
donation_account, _ = Account.objects.get_or_create(
account_category=AccountCategory.MEMBER_DONATION,
)
liability_account, _ = Account.objects.get_or_create(
account_category=AccountCategory.LIABILITY,
)
return (
fee_account,
donation_account,
liability_account,
)
def _import_real_transactions(real_transactions):
ids = []
for real_transaction in real_transactions:
if parse_date(real_transaction['booking_date'] or real_transaction['due_date']).year != 2015:
continue
rt, _ = RealTransaction.objects.get_or_create(
channel=TransactionChannel.BANK,
value_datetime=localize(parse_date(real_transaction['booking_date'] or real_transaction['due_date'])),
amount=real_transaction['amount'],
purpose=real_transaction['reference'],
originator=real_transaction.get('transaction_owner') or 'imported',
# TODO: reverses?
importer='shackbureau',
)
ids.append(rt.pk)
return RealTransaction.objects.filter(pk__in=ids)
def _import_inflows(member, virtual_transactions, real_transactions):
fee_account, donation_account, liability_account = _get_main_accounts()
inflows = [v for v in virtual_transactions if v['booking_type'] == 'deposit']
for inflow in inflows:
if parse_date(inflow['due_date']) is None or parse_date(inflow['due_date']).year != 2015:
continue
account = fee_account if inflow['transaction_type'] == 'membership fee' else donation_account
possible_real_transaction = real_transactions.filter(
virtual_transactions__isnull=True,
amount=abs(Decimal(inflow['amount'])),
value_datetime=localize(parse_date(inflow['due_date'])),
purpose=inflow['payment_reference'],
)
if possible_real_transaction.count() == 1:
real_transaction = possible_real_transaction.first()
VirtualTransaction.objects.get_or_create(
destination_account=account,
source_account=None,
member=member,
amount=abs(Decimal(inflow['amount'])),
value_datetime=localize(parse_date(inflow['due_date'])),
real_transaction=real_transaction,
)
elif possible_real_transaction.count() == 0:
print(f'Found no transaction matching our query: {inflow}')
elif possible_real_transaction.count() > 1:
print(f'Found more than one transactions matching our query: {possible_real_transaction.values_list("pk", flat=True)}')
def _import_transactions(member_data, member):
real_transactions = member_data.get('bank_transactions')
virtual_transactions = member_data.get('account_transactions')
real_transactions = _import_real_transactions(real_transactions)
# _import_fee_claims(member, virtual_transactions)
_import_inflows(member, virtual_transactions, real_transactions)
def import_member(member_data):
member, _ = Member.objects.update_or_create(
number=member_data['number'],
defaults={
'name': member_data['name'],
'address': member_data['address'],
'email': member_data['email'],
})
profile, _ = ShackProfile.objects.update_or_create(
member=member,
defaults={
'has_loeffelhardt_account': member_data.get('has_loeffelhardt_account', False),
'has_matomat_key': member_data.get('has_matomat_key', False),
'has_metro_card': member_data.get('has_metro_card', False),
'has_safe_key': member_data.get('has_safe_key', False),
'has_selgros_card': member_data.get('has_selgros_card', False),
'has_shack_iron_key': member_data.get('has_shack_iron_key', False),
'has_snackomat_key': member_data.get('has_snackomat_key', False),
'is_keyholder': member_data.get('is_keyholder', False),
'signed_DSV': member_data.get('signed_DSV', False),
'ssh_public_key': member_data.get('ssh_public_key', False),
})
memberships = member_data.get('memberships')
last = None
for membership in sorted(memberships, key=lambda m: m['membership_start']):
obj, _ = Membership.objects.update_or_create(
member=member,
start=parse_date(membership['membership_start']),
defaults={
'amount': Decimal(membership['membership_fee_monthly'])*membership['membership_fee_interval'],
'interval': membership['membership_fee_interval'],
})
if last:
last.end = obj.start - timedelta(days=1)
last.save(update_fields=['end'])
last = obj
if member_data['leave_date']:
last.end = parse_date(member_data['leave_date'])
last.save(update_fields=['end'])
if member_data['payment_type'].lower() == 'sepa':
_import_sepa(member_data, member)
for key in ['birth_date', 'nick', 'phone_number']:
value = member_data.get(f'profile__{key}')
if not value and key == 'birth_date':
value = '1970-1-1'
if value:
setattr(member.profile_profile, key, value)
member.profile_profile.save()
_import_transactions(member_data, member)
def import_members(data):
for member in data:
import_member(member)
class Command(BaseCommand):
help = 'Imports a shackbureau json export'
def add_arguments(self, parser):
parser.add_argument('path', type=str)
@transaction.atomic
def handle(self, *args, **options):
path = options.get('path')
with open(path) as export:
data = json.load(export)
import_members(data['members'])
_import_real_transactions(data['unresolved_bank_transactions'])

View File

@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.8 on 2018-01-13 13:30
from __future__ import unicode_literals
import annoying.fields
from django.db import migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('byro_shackspace', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='shackprofile',
name='member',
field=annoying.fields.AutoOneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile_shack', to='members.Member'),
),
]

View File

@ -1,20 +0,0 @@
from annoying.fields import AutoOneToOneField
from django.db import models
class ShackProfile(models.Model):
member = AutoOneToOneField(
to='members.Member',
on_delete=models.CASCADE,
related_name='profile_shack',
)
has_loeffelhardt_account = models.BooleanField(default=False)
has_matomat_key = models.BooleanField(default=False)
has_metro_card = models.BooleanField(default=False)
has_safe_key = models.BooleanField(default=False)
has_selgros_card = models.BooleanField(default=False)
has_shack_iron_key = models.BooleanField(default=False)
has_snackomat_key = models.BooleanField(default=False)
is_keyholder = models.BooleanField(default=False)
signed_DSV = models.BooleanField(default=False)
ssh_public_key = models.TextField(null=True, blank=True)

View File

@ -1,9 +0,0 @@
from django.dispatch import receiver
from byro.members.signals import new_member
@receiver(new_member)
def add_member_to_mailman(sender, signal, **kwargs):
member = sender
# TODO: magic happens here

View File

@ -1,936 +0,0 @@
{
"members": [
{
"number": "-1",
"name": "Max Mustermann",
"address": "Max Mustermann\nMusterstrasse 1\n70000 Berlin",
"email": "max@example.org",
"join_date": "2014-09-01",
"leave_date": "",
"payment_type": "transfer",
"sepa__iban": null,
"sepa__mandate_reason": "shack e.V. Mitgliedsbeitrag ID -1",
"sepa__zip_code": null,
"sepa__country": "Deutschland",
"sepa__city": null,
"sepa__bic": null,
"sepa__address": null,
"sepa__fullname": null,
"sepa__issue_date": null,
"sepa__institute": null,
"sepa__mandate_reference": "SHACKEVBEITRAGID-1",
"profile__birth_date": "",
"profile__nick": "max",
"profile__phone_number": "",
"memberships": [
{
"membership_start": "2014-09-01",
"membership_fee_monthly": "20.00",
"membership_type": "full",
"membership_fee_interval": 1
}
],
"bank_transactions": [
{
"amount": "40.00",
"booking_date": "2014-10-13",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2014-10-27",
"reference": "Muustermann",
"transaction_owner": "",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2014-11-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2014-12-29",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-01-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-02-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-03-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-04-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-05-26",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-06-29",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-07-23",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-08-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-09-28",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-10-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-11-27",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2015-12-28",
"reference": "Mustermann",
"transaction_owner": null,
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-01-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-02-29",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-03-29",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-04-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-05-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-06-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-07-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-08-29",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-09-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-11-28",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-10-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2016-12-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2017-02-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2017-01-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
},
{
"amount": "20.00",
"booking_date": "2017-03-27",
"reference": "Mitgliedsbeitrag ID -1 ",
"transaction_owner": "Max Mustermann",
"debitor_id": "None"
}
],
"account_transactions": [
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 12/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-12-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 11/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-11-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 10/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-10-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 9/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-09-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 8/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-08-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 7/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-07-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 6/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-06-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 5/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-05-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 4/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-04-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 3/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-03-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 2/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-02-01"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 1/2018 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2018-01-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 12/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-12-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 11/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-11-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 10/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-10-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 9/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-09-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 8/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-08-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 7/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-07-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 6/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-06-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 5/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-05-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 4/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-04-01"
},
{
"amount": "20.00",
"booking_date": "2017-04-18",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2017-03-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 3/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-03-01"
},
{
"amount": "20.00",
"booking_date": "2017-03-07",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2017-02-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 2/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-02-01"
},
{
"amount": "20.00",
"booking_date": "2017-03-07",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2017-01-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 1/2017 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2017-01-01"
},
{
"amount": "20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-12-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 12/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-12-01"
},
{
"amount": "20.00",
"booking_date": "2016-12-15",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-11-28"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 11/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-11-01"
},
{
"amount": "20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-10-27"
},
{
"amount": "-20.00",
"booking_date": "2017-01-25",
"payment_reference": "Mitgliedsbeitragsforderung 10/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-10-01"
},
{
"amount": "20.00",
"booking_date": "2016-12-15",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-09-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 9/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-09-01"
},
{
"amount": "20.00",
"booking_date": "2016-12-15",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-08-29"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 8/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-08-01"
},
{
"amount": "20.00",
"booking_date": "2016-12-15",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-07-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 7/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-07-01"
},
{
"amount": "20.00",
"booking_date": "2016-12-15",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-06-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 6/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-06-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-26",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-05-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 5/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-05-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-26",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-04-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 4/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-04-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-26",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-03-29"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 3/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-03-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-26",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-02-29"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 2/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-02-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-26",
"payment_reference": "Mitgliedsbeitrag ID -1 ",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2016-01-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 1/2016 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2016-01-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-12-28"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 12/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-12-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-11-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 11/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-11-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-10-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 10/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-10-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-09-28"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 9/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-09-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-08-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 8/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-08-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-07-23"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 7/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-07-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-06-29"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 6/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-06-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-05-26"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 5/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-05-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-04-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 4/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-04-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-03-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 3/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-03-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-02-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 2/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-02-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-12",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2015-01-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 1/2015 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2015-01-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2014-12-29"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 12/2014 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2014-12-01"
},
{
"amount": "20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2014-11-27"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 11/2014 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2014-11-01"
},
{
"amount": "20.00",
"booking_date": "2014-10-27",
"payment_reference": "Mustermann\nNone",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2014-10-27"
},
{
"amount": "40.00",
"booking_date": "2016-06-04",
"payment_reference": "Mustermann",
"transaction_type": "membership fee",
"booking_type": "deposit",
"due_date": "2014-10-13"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 10/2014 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2014-10-01"
},
{
"amount": "-20.00",
"booking_date": "2016-06-04",
"payment_reference": "Mitgliedsbeitragsforderung 9/2014 ID -1",
"transaction_type": "membership fee",
"booking_type": "fee_claim",
"due_date": "2014-09-01"
}
]
}
],
"unresolved_bank_transactions": [
{
"amount": "-123.00",
"booking_date": "2017-06-01",
"debitor_id": "None",
"reference": "Miete + Betriebskostenabsch Dauerauftrag: 11",
"transaction_owner": "Fritz Vermieter"
},
{
"amount": "10.00",
"booking_date": "2017-01-13",
"debitor_id": "None",
"reference": "Spende mustermann ",
"transaction_owner": ""
}
]
}

View File

@ -1,7 +0,0 @@
Kontonummer;Buchungstag;Wertstellung;Auftraggeber/Empfänger;Buchungstext;VWZ1;VWZ2;VWZ3;VWZ4;VWZ5;VWZ6;VWZ7;VWZ8;VWZ9;VWZ10;VWZ11;VWZ12;VWZ13;VWZ14;Betrag;Kontostand;Währung
7016809500;30.11.2017;30.11.2017;;"Kontoführung";Abrechnung vom 30.11.2017;;;;;;;;;;;;;;-1,50;;EUR
7016809500;30.11.2017;30.11.2017;Ernie u. Bert;"Dauerauftrag-Gutschrift";Mitgliedsbeitrag ID 1;;;;;;;;;;;;;;20,00;;EUR
7016809500;03.11.2017;03.11.2017;Unfähig zu Überweisen;"Dauerauftrag-Gutschrift";Monatsbeitrag;;;;;;;;;;;;;;20,00;;EUR
7016809500;30.11.2017;30.11.2017;Strom Schmeckt Aua;"SEPA-Basislastschrift";104223-11/2017 STROM;;;;;;;;;;;;;;-555,00;;EUR
7016809500;03.11.2017;03.11.2017;Tolles Mitglied;"Internet-Euro-Überweisung";BIC:SOLADECHAOS;IBAN:DE42422300200008416523;Datum: 03.11.17 Zeit: 14:04;UFT 0000000000 TAN 444444;Erstattung Einkauf;;;;;;;;;;-103,90;;EUR
7016809500;03.11.2017;03.11.2017;Doofes Mitglied;"Rücklastschrift";shack e.V. Mitgliedsbeitrag;ID 2;Fremdentgelte: 1,90 EUR;MS03: Institut ohne Rückg.-;Grund/Rückscheck;Originalbetr.:;8,00 EUR;Eigene Geb.: 2,50 EUR;;;;;;;-12,40;;EUR
1 Kontonummer Buchungstag Wertstellung Auftraggeber/Empfänger Buchungstext VWZ1 VWZ2 VWZ3 VWZ4 VWZ5 VWZ6 VWZ7 VWZ8 VWZ9 VWZ10 VWZ11 VWZ12 VWZ13 VWZ14 Betrag Kontostand Währung
2 7016809500 30.11.2017 30.11.2017 Kontoführung Abrechnung vom 30.11.2017 -1,50 EUR
3 7016809500 30.11.2017 30.11.2017 Ernie u. Bert Dauerauftrag-Gutschrift Mitgliedsbeitrag ID 1 20,00 EUR
4 7016809500 03.11.2017 03.11.2017 Unfähig zu Überweisen Dauerauftrag-Gutschrift Monatsbeitrag 20,00 EUR
5 7016809500 30.11.2017 30.11.2017 Strom Schmeckt Aua SEPA-Basislastschrift 104223-11/2017 STROM -555,00 EUR
6 7016809500 03.11.2017 03.11.2017 Tolles Mitglied Internet-Euro-Überweisung BIC:SOLADECHAOS IBAN:DE42422300200008416523 Datum: 03.11.17 Zeit: 14:04 UFT 0000000000 TAN 444444 Erstattung Einkauf -103,90 EUR
7 7016809500 03.11.2017 03.11.2017 Doofes Mitglied Rücklastschrift shack e.V. Mitgliedsbeitrag ID 2 Fremdentgelte: 1,90 EUR MS03: Institut ohne Rückg.- Grund/Rückscheck Originalbetr.: 8,00 EUR Eigene Geb.: 2,50 EUR -12,40 EUR

View File

@ -1,41 +0,0 @@
import os.path
import pytest
from byro_shackspace.utils import process_bank_csv
from django.core.files.uploadedfile import InMemoryUploadedFile
from byro.bookkeeping.models import RealTransactionSource
@pytest.fixture
def bank_transaction_csv_file():
filename = os.path.join(os.path.dirname(__file__), 'fixtures/transactions.csv')
actual_file = open(filename, encoding='iso-8859-1')
f = InMemoryUploadedFile(
file=actual_file,
field_name=None,
name='transactions.csv',
content_type='text',
size=len(actual_file.read()),
charset='iso-8859-1',
)
return RealTransactionSource.objects.create(source_file=f)
@pytest.mark.django_db
def test_bank_import(bank_transaction_csv_file):
assert bank_transaction_csv_file.bookings.count() == 0
process_bank_csv(bank_transaction_csv_file, None)
bank_transaction_csv_file.refresh_from_db()
assert bank_transaction_csv_file.bookings.count() == 6
@pytest.mark.django_db
def test_bank_import_no_duplicates(bank_transaction_csv_file):
assert bank_transaction_csv_file.bookings.count() == 0
process_bank_csv(bank_transaction_csv_file, None)
bank_transaction_csv_file.refresh_from_db()
assert bank_transaction_csv_file.bookings.count() == 6
process_bank_csv(bank_transaction_csv_file, None)
bank_transaction_csv_file.refresh_from_db()
assert bank_transaction_csv_file.bookings.count() == 6

View File

@ -1,7 +0,0 @@
import os.path
def test_file_encoding():
filename = os.path.join(os.path.dirname(__file__), 'fixtures/transactions.csv')
with open(filename, encoding='iso-8859-1') as fp:
assert len(fp.read()) == 1086

View File

@ -1,130 +0,0 @@
import csv
import os.path
import re
from datetime import datetime
from decimal import Decimal
from django.conf import settings
from django.dispatch import receiver
from django.utils.timezone import now
from byro.bookkeeping.models import (
Account, AccountCategory, Booking, Transaction,
)
from byro.bookkeeping.signals import process_csv_upload, process_transaction
from byro.bookkeeping.special_accounts import SpecialAccounts
from byro.common.models import Configuration
from byro.members.models import Member
@receiver(process_csv_upload)
def process_bank_csv(sender, signal, **kwargs):
source = sender
filename = os.path.join(settings.MEDIA_ROOT, source.source_file.name)
reader = csv.DictReader(open(filename, encoding='iso-8859-1'), delimiter=';', quotechar='"')
booking_timestamp = now()
account = SpecialAccounts.bank
for line in reader:
if not line:
continue
reference = ''
for key in reader.fieldnames:
if key.startswith('VWZ'):
reference += line[key] + ' '
amount = Decimal(line.get('Betrag').replace('.', '').replace(',', '.'))
if amount < 0:
amount = -amount
booking_type = 'c'
else:
booking_type = 'd'
params = dict(
memo=reference,
amount=amount,
importer='shack_bank_csv_importer',
)
data = {
'csv_line': line,
'other_party': "{}".format(line.get('Auftraggeber/Empfänger', '<leer>')),
}
if booking_type == 'c':
params['credit_account'] = account
else:
params['debit_account'] = account
booking = account.bookings.filter(
transaction__value_datetime=datetime.strptime(line.get('Buchungstag'), '%d.%m.%Y'),
**params
).first()
if not booking:
t = Transaction.objects.create(
value_datetime=datetime.strptime(line.get('Buchungstag'), '%d.%m.%Y'),
)
Booking.objects.create(
transaction=t,
booking_datetime=booking_timestamp,
source=source,
data=data,
**params
)
return True
@receiver(process_transaction)
def match_transaction(sender, signal, **kwargs):
transaction = sender
if transaction.is_read_only:
return False
if transaction.is_balanced:
return False
uid, score = reference_parser(reference=transaction.find_memo())
member = None
try:
member = Member.objects.get(number=uid)
except Member.DoesNotExist:
return False
balances = transaction.balances
data = {
'amount': abs(balances['debit'] - balances['credit']),
'account': SpecialAccounts.fees_receivable,
'member': member,
}
if balances['debit'] > balances['credit']:
transaction.credit(**data)
else:
transaction.debit(**data)
return True
def reference_parser(reference):
if not reference:
return (False, 99)
reference = reference.lower()
regexes = (
r'.*mitgliedsbeitrag\s+id\s+(?P<ID>\d{1,4})\s.*',
r'.*id\s+(?P<ID>\d{1,4})\smitgliedsbeitrag.*',
# r'.*id\s+(?P<ID>\d{1,4})\s.*',
r'.*mitgliedsbeitrag.*id\s+(?P<ID>\d{1,4})\s.*',
r'.*mitgliedsbeitrag\s+(?P<ID>\d{1,4})\s.*',
r'.*beitrag\s+mitglied\s+(?P<ID>\d{1,4})\s.*',
r'.*mitgliedsbeitrag.*\s+(?P<ID>\d{1,4})[^\d].*',
# r'.*id(?P<ID>\d{1,4})\s+zr\d+.*',
# r'.*id\s+(?P<ID>\d{1,4}),\s+zr\s+\d+.*',
r'.*mitgliedsbeitrag\s+id[.:-_](?P<ID>\d{1,4})\s.*',
)
for score, regex in enumerate(regexes, 1):
hit = re.match(regex, reference)
if hit:
return (int(hit.groupdict().get('ID')), score)
return (False, 99)

View File

@ -23,12 +23,12 @@ cmdclass = {
setup( setup(
name='byro-shackspace', name='byro-leinelab',
version='0.0.0', version='0.0.0',
description='', description='',
long_description=long_description, long_description=long_description,
url='https://github.com/byro/byro-shackspace', url='https://github.com/byro/byro-leinelab',
author='shackspace', author='leinelab',
author_email='', author_email='',
license='Apache Software License', license='Apache Software License',
@ -38,6 +38,6 @@ setup(
cmdclass=cmdclass, cmdclass=cmdclass,
entry_points=""" entry_points="""
[byro.plugin] [byro.plugin]
byro_shackspace=byro_shackspace:ByroPluginMeta byro_leinelab=byro_leinelab:ByroPluginMeta
""", """,
) )