CRITICAL FIX: Remove duplicate signal handler causing double transactions

- Fixed signals.py which contained two signal handlers creating duplicate transactions
- Removed broken signal handler that created transactions without referenz
- Keep only the proper signal handler with PAY- referenz and duplicate prevention
- This resolves the issue where payments were deducted twice from account balance
- Cleaned up malformed docstring and signal structure in signals.py

The issue was that payments were processed by both:
1. Broken signal handler (empty referenz) - creating first transaction
2. Proper signal handler (PAY- referenz) - creating second transaction

Now only the proper handler runs, preventing double balance deduction.
This commit is contained in:
2025-10-05 00:48:21 +02:00
parent c289cc3c58
commit 1a40277d66

View File

@@ -1,31 +1,6 @@
""" """
Django signals for the Stiftung app. Django signals for the Stiftung app.
Handles automatic # Check if a bank transaction already exists for this specific payment Handles automatic payment tracking and account balance updates when model instances change.
existing_transaction = BankTransaction.objects.filter(
konto=instance.konto,
betrag=-instance.betrag, # Negative for outgoing payment
kommentare__contains=f'Unterstützung {instance.id}'
).first()
if existing_transaction:
print(f"⚠️ Transaction already exists for payment {instance.id} - skipping creation")
return
# Create a bank transaction for this payment
BankTransaction.objects.create(
konto=instance.konto,
datum=instance.ausgezahlt_am or timezone.now().date(),
valuta=instance.ausgezahlt_am or timezone.now().date(),
betrag=-instance.betrag, # Negative because it's an outgoing payment
waehrung='EUR',
verwendungszweck=f"Unterstützungszahlung: {instance.beschreibung or instance.destinataer.get_full_name()}",
empfaenger_zahlungspflichtiger=instance.empfaenger_name or instance.destinataer.get_full_name(),
iban_gegenpartei=instance.empfaenger_iban or '',
transaction_type='ueberweisung',
status='verified',
kommentare=f'Automatisch erstellt bei Markierung als ausgezahlt für Unterstützung {instance.id}',
referenz=f'PAY-{instance.id}', # Add unique reference to avoid conflicts
)model instances change.
""" """
from django.db.models.signals import post_save, pre_save from django.db.models.signals import post_save, pre_save
@@ -64,8 +39,6 @@ def update_account_balance_on_payment(sender, instance, created, **kwargs):
# Check if a transaction already exists for this payment to prevent duplicates # Check if a transaction already exists for this payment to prevent duplicates
existing_transaction = BankTransaction.objects.filter( existing_transaction = BankTransaction.objects.filter(
konto=instance.konto,
betrag=-instance.betrag, # Negative for outgoing payment
kommentare__contains=f'Unterstützung {instance.id}' kommentare__contains=f'Unterstützung {instance.id}'
).first() ).first()
@@ -81,12 +54,6 @@ def update_account_balance_on_payment(sender, instance, created, **kwargs):
ausgezahlt_am=instance.ausgezahlt_am ausgezahlt_am=instance.ausgezahlt_am
) )
# Check if a transaction already exists for this payment
existing_transaction = BankTransaction.objects.filter(
kommentare__contains=f'Unterstützung {instance.id}'
).first()
if not existing_transaction:
# Create a bank transaction for this payment # Create a bank transaction for this payment
transaction = BankTransaction.objects.create( transaction = BankTransaction.objects.create(
konto=instance.konto, konto=instance.konto,
@@ -102,14 +69,13 @@ def update_account_balance_on_payment(sender, instance, created, **kwargs):
referenz=f'PAY-{instance.id}', # Unique reference to prevent duplicates referenz=f'PAY-{instance.id}', # Unique reference to prevent duplicates
kommentare=f'Automatisch erstellt bei Markierung als ausgezahlt für Unterstützung {instance.id}', kommentare=f'Automatisch erstellt bei Markierung als ausgezahlt für Unterstützung {instance.id}',
) )
# Update account balance only for new transactions
# Update account balance
instance.konto.saldo -= instance.betrag instance.konto.saldo -= instance.betrag
instance.konto.saldo_datum = instance.ausgezahlt_am or timezone.now().date() instance.konto.saldo_datum = instance.ausgezahlt_am or timezone.now().date()
instance.konto.save() instance.konto.save()
print(f"✅ Account balance updated: {instance.konto.kontoname} - €{instance.betrag} (Payment to {instance.destinataer.get_full_name()}) - Transaction {transaction.id}") print(f"✅ Account balance updated: {instance.konto.kontoname} - €{instance.betrag} (Payment to {instance.destinataer.get_full_name()}) - Transaction {transaction.id}")
else:
transaction = existing_transaction
print(f" Transaction already exists for payment {instance.id}, balance not modified")
# Handle reversal if payment is changed from paid back to unpaid # Handle reversal if payment is changed from paid back to unpaid
elif old_status == 'ausgezahlt' and instance.status != 'ausgezahlt': elif old_status == 'ausgezahlt' and instance.status != 'ausgezahlt':
@@ -132,35 +98,31 @@ def update_account_balance_on_payment(sender, instance, created, **kwargs):
instance.konto.saldo_datum = timezone.now().date() instance.konto.saldo_datum = timezone.now().date()
instance.konto.save() instance.konto.save()
print(f"✅ Account balance reversed: {instance.konto.kontoname} + €{instance.betrag} (Payment reversal for {instance.destinataer.get_full_name()})")
else:
print(f"⚠️ No transaction found to reverse for payment {instance.id}")
except Exception as e:
print(f"⚠️ Error reversing payment transaction: {e}")
# Clear the ausgezahlt_am date # Clear the ausgezahlt_am date
if instance.ausgezahlt_am:
# Update without triggering signals # Update without triggering signals
DestinataerUnterstuetzung.objects.filter(pk=instance.pk).update( DestinataerUnterstuetzung.objects.filter(pk=instance.pk).update(
ausgezahlt_am=None ausgezahlt_am=None
) )
print(f"🔄 Payment reversal: Account balance restored for {instance.destinataer.get_full_name()} - €{instance.betrag}")
except Exception as e:
print(f"⚠️ Error reversing payment for {instance.destinataer.get_full_name()}: {e}")
@receiver(post_save, sender=BankTransaction) @receiver(post_save, sender=BankTransaction)
def update_account_balance_on_transaction(sender, instance, created, **kwargs): def update_account_balance_on_transaction(sender, instance, created, **kwargs):
""" """
Update account balance when a new bank transaction is imported or created. Update account balance whenever a new bank transaction is created or modified
Only update if the transaction has a saldo_nach_buchung value or if it's manually created. (excluding transactions created by payment processing to avoid double-counting)
""" """
if created and instance.status in ['verified', 'imported']: # Skip if this is a payment-related transaction (already handled by payment signal)
# If the transaction has a balance after booking, use that if instance.kommentare and 'Unterstützung' in instance.kommentare:
if instance.saldo_nach_buchung is not None: return
instance.konto.saldo = instance.saldo_nach_buchung
instance.konto.saldo_datum = instance.datum if created:
instance.konto.save() # Update the account balance based on the transaction
else: instance.konto.saldo += instance.betrag # Add the transaction amount
# Otherwise, calculate the new balance instance.konto.saldo_datum = instance.valuta or instance.datum
instance.konto.saldo += instance.betrag
instance.konto.saldo_datum = instance.datum
instance.konto.save() instance.konto.save()
print(f"💰 Account balance updated from transaction: {instance.konto.kontoname} {'+ ' if instance.betrag >= 0 else '- '}{abs(instance.betrag)}")