byro-leinelab/byro_shackspace/utils.py

93 lines
3.3 KiB
Python
Raw Normal View History

2018-01-11 18:54:42 +01:00
import csv
import re
2018-01-13 13:05:49 +01:00
from datetime import datetime
2018-01-11 18:54:42 +01:00
from decimal import Decimal
2018-01-11 20:20:05 +01:00
from django.dispatch import receiver
2018-01-11 19:24:13 +01:00
from django.utils.timezone import now
2018-01-11 18:54:42 +01:00
2018-01-13 13:05:49 +01:00
from byro.bookkeeping.models import (
Account, AccountCategory, RealTransaction,
TransactionChannel, VirtualTransaction,
)
from byro.bookkeeping.signals import (
derive_virtual_transactions, process_csv_upload,
)
2018-01-11 19:24:13 +01:00
from byro.members.models import Member
2018-01-11 18:54:42 +01:00
2018-01-13 13:05:49 +01:00
@receiver(process_csv_upload)
def process_bank_csv(sender, signal, **kwargs):
source = sender
2018-01-11 20:20:05 +01:00
reader = csv.DictReader(open(source.source_file.name, encoding='iso-8859-1'), delimiter=';', quotechar='"')
2018-01-11 19:24:13 +01:00
booking_timestamp = now()
2018-01-11 18:54:42 +01:00
2018-01-11 19:24:13 +01:00
for line in reader:
if not line:
continue
reference = ''
for key in line.keys():
if key.startswith('VWZ'):
2018-01-11 20:20:05 +01:00
reference += line[key] + ' '
2018-01-11 18:54:42 +01:00
2018-01-13 13:52:59 +01:00
RealTransaction.objects.get_or_create(
2018-01-11 19:24:13 +01:00
channel=TransactionChannel.BANK,
value_datetime=datetime.strptime(line.get('Buchungstag'), '%d.%m.%Y'),
amount=Decimal(line.get('Betrag').replace('.', '').replace(',', '.')),
purpose=reference,
2018-01-11 20:20:05 +01:00
originator=line.get('Auftraggeber/Empfänger', '<leer>'),
2018-01-11 19:24:13 +01:00
importer='shack_bank_csv_importer',
2018-01-13 19:14:00 +01:00
defaults={'source': source, 'booking_datetime': booking_timestamp, 'data': line},
2018-01-11 19:24:13 +01:00
)
2018-01-13 13:05:49 +01:00
return True
2018-01-11 18:54:42 +01:00
2018-01-11 20:20:16 +01:00
@receiver(derive_virtual_transactions)
def match_transaction(sender, signal, **kwargs):
transaction = sender
2018-01-13 13:05:49 +01:00
uid, score = reference_parser(reference=transaction.purpose)
2018-01-11 19:24:13 +01:00
member = None
try:
2018-01-11 20:20:16 +01:00
member = Member.objects.get(number=uid)
2018-01-11 19:24:13 +01:00
except Member.DoesNotExist:
2018-01-11 20:20:16 +01:00
return
account = Account.objects.get(account_category=AccountCategory.MEMBER_FEES)
data = {
'amount': transaction.amount,
2018-01-13 13:05:49 +01:00
'destination_account': account,
'value_datetime': transaction.value_datetime,
2018-01-11 20:20:16 +01:00
'member': member,
}
virtual_transaction = VirtualTransaction.objects.filter(**data).first()
if virtual_transaction and virtual_transaction.real_transaction != transaction:
raise Exception(f'RealTransaction {transaction.id} cannot be matched! There is already a VirtualTransaction ({virtual_transaction.id}) that is too similar. It is matched to RealTransaction {virtual_transaction.real_transaction.id}.')
if not virtual_transaction:
data['real_transaction'] = transaction
virtual_transaction = VirtualTransaction.objects.create(**data)
return [virtual_transaction]
2018-01-11 18:54:42 +01:00
2018-01-13 13:05:49 +01:00
def reference_parser(reference):
2018-01-11 19:24:13 +01:00
reference = reference.lower()
2018-01-11 18:54:42 +01:00
2018-01-11 19:24:13 +01:00
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.*',
)
2018-01-11 18:54:42 +01:00
2018-01-11 19:24:13 +01:00
for score, regex in enumerate(regexes, 1):
hit = re.match(regex, reference)
if hit:
return (int(hit.groupdict().get('ID')), score)
2018-01-11 18:54:42 +01:00
2018-01-11 19:24:13 +01:00
return (False, 99)