From c6dd707704aa787fae5b2e57a1869c83772a7e55 Mon Sep 17 00:00:00 2001 From: Job Doesburg Date: Sat, 28 Oct 2023 14:59:31 +0200 Subject: [PATCH] Book external invoices for event registrations on the correct date --- website/moneybirdsynchronization/models.py | 38 +++++++++++++--------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/website/moneybirdsynchronization/models.py b/website/moneybirdsynchronization/models.py index c4d9f0fff..0f299acbc 100644 --- a/website/moneybirdsynchronization/models.py +++ b/website/moneybirdsynchronization/models.py @@ -10,7 +10,7 @@ from django.utils.translation import gettext_lazy as _ from events.models import EventRegistration -from members.models import Member, Membership +from members.models import Member from moneybirdsynchronization.moneybird import get_moneybird_api_service from payments.models import BankAccount, Payment from payments.payables import payables @@ -47,7 +47,7 @@ def project_name_for_payable_model(obj) -> Optional[str]: def date_for_payable_model(obj) -> Union[datetime.datetime, datetime.date]: if isinstance(obj, EventRegistration): - return obj.event.start + return obj.date.date() if isinstance(obj, FoodOrder): return obj.food_event.event.start if isinstance(obj, Order): @@ -58,16 +58,25 @@ def date_for_payable_model(obj) -> Union[datetime.datetime, datetime.date]: raise ValueError(f"Unknown payable model {obj}") -def ledger_id_for_payable_model(obj) -> Optional[int]: +def period_for_payable_model(obj) -> Optional[str]: if isinstance(obj, (Registration, Renewal)): - return settings.MONEYBIRD_CONTRIBUTION_LEDGER_ID + if obj.membership is not None: + # Only bill for the start date, ignore the until date. + date = obj.membership.since + return f"{date.strftime('%Y%m%d')}..{date.strftime('%Y%m%d')}" return None -def membership_to_mb_period(membership: Membership) -> str: - """Convert a membership to a Moneybird period.""" - start_date = membership.since - return f"{start_date.strftime('%Y%m%d')}..{start_date.strftime('%Y%m%d')}" +def tax_rate_for_payable_model(obj) -> Optional[int]: + if isinstance(obj, (Registration, Renewal)): + return settings.MONEYBIRD_ZERO_TAX_RATE_ID + return None + + +def ledger_id_for_payable_model(obj) -> Optional[int]: + if isinstance(obj, (Registration, Renewal)): + return settings.MONEYBIRD_CONTRIBUTION_LEDGER_ID + return None class MoneybirdProject(models.Model): @@ -251,6 +260,8 @@ def to_moneybird(self): moneybird_contact, __ = MoneybirdContact.objects.get_or_create( member=self.payable.payment_payer ) + # If the contact is not yet in Moneybird, create it + # This should not happen in practice, but it is a nice fallback if moneybird_contact.moneybird_id is None: # I know this is ugly, but I don't want to totally refactor the app. from moneybirdsynchronization.services import create_or_update_contact @@ -261,6 +272,10 @@ def to_moneybird(self): invoice_date = date_for_payable_model(self.payable_object).strftime("%Y-%m-%d") + period = period_for_payable_model(self.payable_object) + + tax_rate_id = tax_rate_for_payable_model(self.payable_object) + project_name = project_name_for_payable_model(self.payable_object) project_id = None @@ -275,13 +290,6 @@ def to_moneybird(self): ledger_id = ledger_id_for_payable_model(self.payable_object) - period = None - tax_rate_id = None - if isinstance(self.payable_object, (Registration, Renewal)): - tax_rate_id = settings.MONEYBIRD_ZERO_TAX_RATE_ID - if self.payable_object.membership is not None: - period = membership_to_mb_period(self.payable_object.membership) - source_url = settings.BASE_URL + reverse( f"admin:{self.payable_object._meta.app_label}_{self.payable_object._meta.model_name}_change", args=(self.object_id,),