Filter schedules by source.
[wolnelektury.git] / src / club / models.py
index 1a69144..babe6f5 100644 (file)
@@ -51,7 +51,9 @@ class Schedule(models.Model):
     amount = models.DecimalField(_('amount'), max_digits=10, decimal_places=2)
     monthly = models.BooleanField(_('monthly'), default=True)
     yearly = models.BooleanField(_('yearly'), default=False)
     amount = models.DecimalField(_('amount'), max_digits=10, decimal_places=2)
     monthly = models.BooleanField(_('monthly'), default=True)
     yearly = models.BooleanField(_('yearly'), default=False)
-    
+
+    source = models.CharField(_('source'), max_length=255, blank=True)
+
     is_cancelled = models.BooleanField(_('cancelled'), default=False)
     payed_at = models.DateTimeField(_('payed at'), null=True, blank=True)
     started_at = models.DateTimeField(_('started at'), auto_now_add=True)
     is_cancelled = models.BooleanField(_('cancelled'), default=False)
     payed_at = models.DateTimeField(_('payed at'), null=True, blank=True)
     started_at = models.DateTimeField(_('started at'), auto_now_add=True)
@@ -132,8 +134,10 @@ class Membership(models.Model):
     """ Represents a user being recognized as a member of the club. """
     user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
     created_at = models.DateTimeField(_('created at'), auto_now_add=True)
     """ Represents a user being recognized as a member of the club. """
     user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
     created_at = models.DateTimeField(_('created at'), auto_now_add=True)
-    name = models.CharField(max_length=255, blank=True)
-    honorary = models.BooleanField(default=False)
+    name = models.CharField(_('name'), max_length=255, blank=True)
+    manual = models.BooleanField(_('manual'), default=False)
+    notes = models.CharField(_('notes'), max_length=2048, blank=True)
+    updated_at = models.DateField(_('updated at'), auto_now=True, blank=True)
 
     class Meta:
         verbose_name = _('membership')
 
     class Meta:
         verbose_name = _('membership')
@@ -142,6 +146,21 @@ class Membership(models.Model):
     def __str__(self):
         return str(self.user)
 
     def __str__(self):
         return str(self.user)
 
+    def save(self, *args, **kwargs):
+        super().save(*args, **kwargs)
+        self.update_contact()
+
+    def update_contact(self):
+        email = self.user.email
+        if not email:
+            return
+
+        Contact = apps.get_model('messaging', 'Contact')
+        if self.manual:
+            Contact.update(email, Level.MANUAL_MEMBER, self.updated_at)
+        else:
+            Contact.reset(email)
+
     @classmethod
     def is_active_for(cls, user):
         if user.is_anonymous:
     @classmethod
     def is_active_for(cls, user):
         if user.is_anonymous:
@@ -150,7 +169,7 @@ class Membership(models.Model):
             membership = user.membership
         except cls.DoesNotExist:
             return False
             membership = user.membership
         except cls.DoesNotExist:
             return False
-        if membership.honorary:
+        if membership.manual:
             return True
         return Schedule.objects.filter(
                 expires_at__gt=now(),
             return True
         return Schedule.objects.filter(
                 expires_at__gt=now(),
@@ -244,14 +263,55 @@ class PayUOrder(payu_models.Order):
 
     @classmethod
     def send_receipt(cls, email, year):
 
     @classmethod
     def send_receipt(cls, email, year):
+        Contact = apps.get_model('messaging', 'Contact')
+        Funding = apps.get_model('funding', 'Funding')
+        payments = []
+
+        try:
+            contact = Contact.objects.get(email=email)
+        except Contact.DoesNotExist:
+            funding = Funding.objects.filter(
+                email=email,
+                payed_at__year=year,
+                notifications=True).order_by('payed_at').first()
+            if funding is None:
+                print('no notifications')
+                return
+            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')
         qs = cls.objects.filter(status='COMPLETED', schedule__email=email, completed_at__year=year).order_by('completed_at')
-        if not qs.exists(): return
+        for order in qs:
+            payments.append({
+                'timestamp': order.completed_at,
+                'amount': order.get_amount(),
+            })
+
+        fundings = Funding.objects.filter(
+            email=email,
+            payed_at__year=year
+        ).order_by('payed_at')
+        for funding in fundings:
+            payments.append({
+                'timestamp': funding.payed_at,
+                'amount': funding.amount,
+            })
+
+        if not payments: return
+
+        payments.sort(key=lambda x: x['timestamp'])
+
         ctx = {
             "email": email,
             "year": year,
             "next_year": year + 1,
         ctx = {
             "email": email,
             "year": year,
             "next_year": year + 1,
-            "total": qs.aggregate(s=models.Sum('schedule__amount'))['s'],
-            "orders": qs,
+            "total": sum(x['amount'] for x in payments),
+            "payments": payments,
+            "optout": optout,
         }
         temp = tempfile.NamedTemporaryFile(prefix='receipt-', suffix='.pdf', delete=False)
         temp.close()
         }
         temp = tempfile.NamedTemporaryFile(prefix='receipt-', suffix='.pdf', delete=False)
         temp.close()