Add importer manage command
This commit is contained in:
parent
71d31b38c9
commit
344f7417da
146
byro_shackspace/management/commands/import_shackbureau.py
Normal file
146
byro_shackspace/management/commands/import_shackbureau.py
Normal file
@ -0,0 +1,146 @@
|
||||
import json
|
||||
from contextlib import suppress
|
||||
from datetime import datetime, timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
from django.utils.dateparse import parse_date
|
||||
|
||||
from byro.bookkeeping.models import TransactionChannel, RealTransaction, VirtualTransaction, Account, AccountCategory
|
||||
from byro.members.models import Member, Membership
|
||||
|
||||
|
||||
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 _import_transactions(member_data, member):
|
||||
real_transactions = member_data.get('bank_transactions')
|
||||
virtual_transactions = member_data.get('account_transactions')
|
||||
|
||||
transactions = []
|
||||
for real_transaction in real_transactions:
|
||||
transactions.append(RealTransaction(
|
||||
channel=TransactionChannel.BANK,
|
||||
value_datetime=parse_date(real_transaction['booking_date']),
|
||||
amount=real_transaction['amount'],
|
||||
purpose=real_transaction['reference'],
|
||||
originator=real_transaction.get('transaction_owner') or 'imported',
|
||||
# TODO: reverses?
|
||||
importer='shackbureau',
|
||||
))
|
||||
|
||||
real_ids = [rt.pk for rt in RealTransaction.objects.bulk_create(transactions)]
|
||||
member.refresh_from_db()
|
||||
|
||||
claims = [v for v in virtual_transactions if v['booking_type'] == 'fee_claim']
|
||||
inflows = [v for v in virtual_transactions if v['booking_type'] == 'deposit']
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
transactions = []
|
||||
for claim in claims:
|
||||
transactions.append(VirtualTransaction(
|
||||
source_account=fee_account,
|
||||
destination_account=liability_account,
|
||||
member=member,
|
||||
amount=abs(Decimal(claim['amount'])),
|
||||
value_datetime=claim['due_date'],
|
||||
))
|
||||
VirtualTransaction.objects.bulk_create(transactions)
|
||||
|
||||
qs = RealTransaction.objects.filter(pk__in=real_ids)
|
||||
for inflow in inflows:
|
||||
account = fee_account if inflow['transaction_type'] == 'membership fee' else donation_account
|
||||
"""
|
||||
{
|
||||
"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"
|
||||
},
|
||||
"""
|
||||
try:
|
||||
real_transaction = qs.get(
|
||||
virtual_transactions__isnull=True,
|
||||
amount=abs(Decimal(inflow['amount'])),
|
||||
value_datetime=inflow['due_date'],
|
||||
purpose=inflow['payment_reference'],
|
||||
)
|
||||
except RealTransaction.DoesNotExist:
|
||||
real_transaction = None
|
||||
|
||||
VirtualTransaction.objects.create(
|
||||
destination_account=account,
|
||||
source_account=liability_account,
|
||||
member=member,
|
||||
amount=abs(Decimal(inflow['amount'])),
|
||||
value_datetime=inflow['due_date'],
|
||||
real_transaction=real_transaction,
|
||||
)
|
||||
|
||||
|
||||
def import_member(member_data):
|
||||
member = Member.objects.create(
|
||||
number=member_data['number'],
|
||||
name=member_data['name'],
|
||||
address=member_data['address'],
|
||||
email=member_data['email'],
|
||||
)
|
||||
memberships = member_data.get('memberships')
|
||||
last = None
|
||||
for membership in sorted(memberships, key=lambda m: m['membership_start']):
|
||||
obj = Membership.objects.create(
|
||||
member=member,
|
||||
start=parse_date(membership['membership_start']),
|
||||
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['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 value:
|
||||
setattr(member.profile_profile, key, value)
|
||||
member.profile_profile.save()
|
||||
_import_transactions(member_data, member)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Imports a frab xml 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)
|
||||
|
||||
for member in data:
|
||||
import_member(member)
|
Loading…
Reference in New Issue
Block a user