byro-leinelab/byro_shackspace/utils.py

131 lines
3.8 KiB
Python
Raw Normal View History

2018-01-11 18:54:42 +01:00
import csv
2018-03-03 18:57:54 +01:00
import os.path
2018-01-11 18:54:42 +01:00
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-07-08 22:07:59 +02:00
from django.conf import settings
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 (
2018-07-08 22:07:59 +02:00
Account, AccountCategory, Booking, Transaction,
2018-01-13 13:05:49 +01:00
)
2018-07-08 22:07:59 +02:00
from byro.bookkeeping.signals import process_csv_upload, process_transaction
from byro.bookkeeping.special_accounts import SpecialAccounts
from byro.common.models import Configuration
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-03-03 18:57:54 +01:00
filename = os.path.join(settings.MEDIA_ROOT, source.source_file.name)
reader = csv.DictReader(open(filename, encoding='iso-8859-1'), delimiter=';', quotechar='"')
2018-01-11 19:24:13 +01:00
booking_timestamp = now()
2018-07-08 22:07:59 +02:00
account = SpecialAccounts.bank
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 reader.fieldnames:
2018-01-11 19:24:13 +01:00
if key.startswith('VWZ'):
2018-01-11 20:20:05 +01:00
reference += line[key] + ' '
2018-01-11 18:54:42 +01:00
2018-07-08 22:07:59 +02:00
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,
2018-01-11 19:24:13 +01:00
importer='shack_bank_csv_importer',
)
2018-07-08 22:07:59 +02:00
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
)
2018-01-13 13:05:49 +01:00
return True
2018-01-11 18:54:42 +01:00
2018-07-08 22:07:59 +02:00
@receiver(process_transaction)
def match_transaction(sender, signal, **kwargs):
transaction = sender
2018-07-08 22:07:59 +02:00
if transaction.is_read_only:
return False
if transaction.is_balanced:
return False
uid, score = reference_parser(reference=transaction.find_memo())
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-07-08 22:07:59 +02:00
return False
2018-01-11 20:20:16 +01:00
2018-07-08 22:07:59 +02:00
balances = transaction.balances
2018-01-11 20:20:16 +01:00
data = {
2018-07-08 22:07:59 +02:00
'amount': abs(balances['debit'] - balances['credit']),
'account': SpecialAccounts.fees_receivable,
2018-01-11 20:20:16 +01:00
'member': member,
}
2018-07-08 22:07:59 +02:00
if balances['debit'] > balances['credit']:
transaction.credit(**data)
else:
transaction.debit(**data)
return True
2018-01-11 20:20:16 +01:00
2018-01-11 18:54:42 +01:00
2018-01-13 13:05:49 +01:00
def reference_parser(reference):
2018-07-08 22:07:59 +02:00
if not reference:
return (False, 99)
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)