# lingo - basket and payment system # Copyright (C) 2015 Entr'ouvert # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import datetime import logging import django.apps import eopayment from django.db import transaction from django.db.models.signals import post_migrate from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext_lazy as _ class AppConfig(django.apps.AppConfig): name = 'combo.apps.lingo' verbose_name = _('Payment') def ready(self): post_migrate.connect(self.post_migrate_handler, sender=self) def post_migrate_handler(self, **kwargs): from .models import PaymentBackend with transaction.atomic(): for payment_backend in PaymentBackend.objects.all(): service_options = payment_backend.service_options transaction_options = {} for parameter in payment_backend.eopayment.get_parameters(scope='transaction'): name = parameter['name'] if name in service_options: transaction_options[name] = service_options.pop(name) if not transaction_options: continue payment_backend.save() for regie in payment_backend.regie_set.all(): # merge old values in new transactions options regie.transaction_options = dict(transaction_options, **regie.transaction_options) regie.save() def get_before_urls(self): from . import urls return urls.urlpatterns def get_extra_manager_actions(self): return [{'href': reverse('lingo-manager-homepage'), 'text': _('Online Payment')}] def hourly(self): self.update_transactions() self.notify_payments() def update_transactions(self): from .models import EXPIRED, Transaction logger = logging.getLogger(__name__) now = timezone.now() to_expire = Transaction.objects.filter( start_date__lt=now - datetime.timedelta(hours=1), end_date__isnull=True ) for transaction in to_expire: logger.info('transaction %r is expired', transaction.order_id) transaction.status = EXPIRED transaction.save() to_retry = Transaction.objects.filter( status__in=(eopayment.PAID, eopayment.ACCEPTED), to_be_paid_remote_items__isnull=False, start_date__gt=now - datetime.timedelta(days=4), ) for transaction in to_retry: transaction.retry_notify_remote_items_of_payments() def notify_payments(self): from combo.apps.lingo.models import BasketItem logger = logging.getLogger(__name__) now = timezone.now() for item in BasketItem.objects.filter( notification_date__isnull=True, cancellation_date__isnull=True, payment_date__lt=now - datetime.timedelta(minutes=5), payment_date__gt=now - datetime.timedelta(minutes=300), ): try: item.notify_payment() except Exception: logger.exception('error in async notification for basket item %s', item.id)