+
+class Ambassador(models.Model):
+ name = models.CharField(_('name'), max_length=255)
+ photo = models.ImageField(_('photo'), blank=True)
+ text = models.CharField(_('text'), max_length=1024)
+
+ class Meta:
+ verbose_name = _('ambassador')
+ verbose_name_plural = _('ambassadors')
+ ordering = ['name']
+
+ def __str__(self):
+ return self.name
+
+
+########
+# #
+# PayU #
+# #
+########
+
+class PayUOrder(payu_models.Order):
+ schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE)
+
+ def get_amount(self):
+ return self.schedule.amount
+
+ def get_buyer(self):
+ return {
+ "email": self.schedule.email,
+ "language": get_language(),
+ }
+
+ def get_description(self):
+ return 'Wolne Lektury'
+
+ def is_recurring(self):
+ return self.schedule.get_payment_method().is_recurring
+
+ def get_card_token(self):
+ return self.schedule.payucardtoken_set.order_by('-created_at').first()
+
+ def get_notify_url(self):
+ return "https://{}{}".format(
+ Site.objects.get_current().domain,
+ reverse('club_payu_notify', args=[self.pk]))
+
+ def get_thanks_url(self):
+ return self.schedule.get_thanks_url()
+
+ def status_updated(self):
+ if self.status == 'COMPLETED':
+ self.schedule.set_payed()
+
+ elif self.status == 'CANCELED' or self.status.startswith('ERR-'):
+ if self.is_recurring() and self.schedule.expires_at:
+ self.schedule.send_email_failed_recurring()
+
+ self.report_activity()
+
+ @property
+ def updated_at(self):
+ try:
+ return self.notification_set.all().order_by('-received_at')[0].received_at
+ except IndexError:
+ return None
+
+ def report_activity(self):
+ if self.status not in ['COMPLETED', 'CANCELED', 'REJECTED']:
+ return
+
+ if self.status != 'COMPLETED':
+ name = settings.CIVICRM_ACTIVITIES['Failed contribution']
+ elif self.is_recurring():
+ name = settings.CIVICRM_ACTIVITIES['Recurring contribution']
+ else:
+ name = settings.CIVICRM_ACTIVITIES['Contribution']
+
+ report_activity.delay(
+ self.schedule.email,
+ self.schedule.key,
+ f'payu:{self.id}',
+ name,
+ self.updated_at,
+ {
+ 'kwota': self.schedule.amount,
+ }
+ )
+
+ @classmethod
+ def send_receipt(cls, email, year, resend=False):
+ Contact = apps.get_model('messaging', 'Contact')
+ Funding = apps.get_model('funding', 'Funding')
+ BillingAgreement = apps.get_model('paypal', 'BillingAgreement')
+ DirectDebit = apps.get_model('pz', 'DirectDebit')
+ Payment = apps.get_model('pz', 'Payment')
+
+ payments = []
+
+ optout = None
+ try:
+ contact = Contact.objects.get(email=email)
+ except Contact.DoesNotExist:
+ funding = Funding.objects.filter(
+ email=email,
+ completed_at__year=year,
+ notifications=True).order_by('completed_at').first()
+ if funding is None:
+ print('no notifications')
+ if not DirectDebit.objects.filter(email=email, optout=False).exists():
+ return
+ else:
+ optout = funding.wl_optout_url()
+ else:
+ if contact.level == Level.OPT_OUT:
+ print('opt-out')
+ return
+ optout = contact.wl_optout_url()
+
+ qs = cls.objects.filter(status='COMPLETED', schedule__email=email, completed_at__year=year).order_by('completed_at')
+ for order in qs:
+ payments.append({
+ 'timestamp': order.completed_at,
+ 'amount': order.get_amount(),
+ })
+
+ for ba in BillingAgreement.objects.filter(schedule__email=email):
+ payments.extend(ba.get_donations(year))
+
+ fundings = Funding.objects.filter(
+ email=email,
+ completed_at__year=year
+ ).order_by('completed_at')
+ for funding in fundings:
+ payments.append({
+ 'timestamp': funding.completed_at,
+ 'amount': funding.amount,
+ })
+
+ for pa in Payment.objects.filter(
+ debit__email=email,
+ realised=True,
+ is_dd=True,
+ booking_date__year=year
+ ):
+ payments.append({
+ 'timestamp': datetime(pa.booking_date.year, pa.booking_date.month, pa.booking_date.day, tzinfo=utc),
+ 'amount': Decimal(str(pa.debit.amount) + '.00')
+ })
+
+
+ if not payments: return
+
+ payments.sort(key=lambda x: x['timestamp'])
+
+ ctx = {
+ "email": email,
+ "year": year,
+ "next_year": year + 1,
+ "total": sum(x['amount'] for x in payments),
+ "payments": payments,
+ "optout": optout,
+ "resend": resend,
+ }
+ temp = tempfile.NamedTemporaryFile(prefix='receipt-', suffix='.pdf', delete=False)
+ temp.close()
+ render_to_pdf(temp.name, 'club/receipt.texml', ctx, {
+ "wl.eps": os.path.join(settings.STATIC_ROOT, "img/wl.eps"),
+ })
+
+ message = EmailMessage(
+ 'Odlicz darowiznę na Wolne Lektury od podatku',
+ template.loader.render_to_string('club/receipt_email.txt', ctx),
+ settings.CLUB_CONTACT_EMAIL, [email]
+ )
+ with open(temp.name, 'rb') as f:
+ message.attach('wolnelektury-darowizny.pdf', f.read(), 'application/pdf')
+ message.send()
+ os.unlink(f.name)
+
+
+class PayUCardToken(payu_models.CardToken):
+ schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE)
+
+
+class PayUNotification(payu_models.Notification):
+ order = models.ForeignKey(PayUOrder, models.CASCADE, related_name='notification_set')