We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
PaymentPrice description is not required by manager but required for __str__
## What kind of an issue is this?

- [x] Bug report


## What is the expected behaviour?

That you can create a PaymentPrice by following the guidelines, which are a required price and an optional description.

## What is the current behaviour?

By creating a PaymentPrice with a required price but no description the system fails with the error message

```
TypeError at /admin/payment/payment/add/
unsupported operand type(s) for +: 'NoneType' and 'str'
```


## How do you reproduce this problem? 

* Create an event with an attached attendance
* Navigate to /admin/payment/payment/add/
* Add a payment to the attendance event you created, without a description (but with a price)
* The system crashes with the error message `unsupported operand type(s) for +: 'NoneType' and 'str'`


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `apps/payment/models.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 import uuid
4 
5 from django.conf import settings
6 from django.contrib.contenttypes.fields import GenericForeignKey
7 from django.contrib.contenttypes.models import ContentType
8 from django.db import models
9 from django.utils import timezone
10 from django.utils.translation import ugettext as _
11 from rest_framework.exceptions import NotAcceptable
12 
13 from apps.events.models import AttendanceEvent, Attendee
14 from apps.marks.models import Suspension
15 
16 User = settings.AUTH_USER_MODEL
17 
18 
19 class Payment(models.Model):
20 
21     TYPE_CHOICES = (
22         (1, _('Umiddelbar')),
23         (2, _('Frist')),
24         (3, _('Utsettelse')),
25     )
26 
27     # Make sure these exist in settings if they are to be used.
28     STRIPE_KEY_CHOICES = (
29         ('arrkom', 'arrkom'),
30         ('prokom', 'prokom'),
31         ('trikom', 'trikom'),
32         ('fagkom', 'fagkom'),
33     )
34 
35     content_type = models.ForeignKey(ContentType)
36     object_id = models.PositiveIntegerField()
37     content_object = GenericForeignKey()
38     stripe_key = models.CharField(
39         _('stripe key'),
40         max_length=10,
41         choices=STRIPE_KEY_CHOICES,
42         default="arrkom"
43     )
44 
45     payment_type = models.SmallIntegerField(_('type'), choices=TYPE_CHOICES)
46 
47     # Optional fields depending on payment type
48     deadline = models.DateTimeField(_("frist"), blank=True, null=True)
49     active = models.BooleanField(default=True)
50     delay = models.SmallIntegerField(_('utsettelse'), blank=True, null=True, default=2)
51 
52     # For logging and history
53     added_date = models.DateTimeField(_("opprettet dato"), auto_now=True)
54     changed_date = models.DateTimeField(auto_now=True, editable=False)
55     last_changed_by = models.ForeignKey(User, editable=False, null=True)  # Blank and null is temperarly
56 
57     def paid_users(self):
58         return [payment_relation.user for payment_relation in self.paymentrelation_set.filter(refunded=False)]
59 
60     def payment_delays(self):
61         return self.paymentdelay_set.filter(active=True)
62 
63     def payment_delay_users(self):
64         return [payment_delay.user for payment_delay in self.payment_delays()]
65 
66     def create_payment_delay(self, user, deadline):
67         payment_delays = self.paymentdelay_set.filter(payment=self, user=user)
68 
69         if payment_delays:
70             for payment_delay in payment_delays:
71                 payment_delay.valid_to = deadline
72                 payment_delay.save()
73         else:
74             PaymentDelay.objects.create(payment=self, user=user, valid_to=deadline)
75 
76     def description(self):
77         if self._is_type(AttendanceEvent):
78             return self.content_object.event.title
79 
80     def get_receipt_description(self):
81         receipt_description = ""
82         description = [' '] * 30
83         temp = self.description()[0:25]
84         description[0:len(temp)+1] = list(temp)
85         for c in description:
86             receipt_description += c
87         return receipt_description
88 
89     def responsible_mail(self):
90         if self._is_type(AttendanceEvent):
91             event_type = self.content_object.event.event_type
92             if event_type == 1 or event_type == 4:  # Sosialt & Utflukt
93                 return settings.EMAIL_ARRKOM
94             elif event_type == 2:  # Bedpres
95                 return settings.EMAIL_BEDKOM
96             elif event_type == 3:  # Kurs
97                 return settings.EMAIL_FAGKOM
98             elif event_type == 5:  # Ekskursjon
99                 return settings.EMAIL_EKSKOM
100             else:
101                 return settings.DEFAULT_FROM_EMAIL
102         else:
103             return settings.DEFAULT_FROM_EMAIL
104 
105     def handle_payment(self, user):
106         if self._is_type(AttendanceEvent):
107             attendee = Attendee.objects.filter(event=self.content_object, user=user)
108 
109             # Delete payment delay objects for the user if there are any
110             delays = PaymentDelay.objects.filter(payment=self, user=user)
111             for delay in delays:
112                 delay.delete()
113 
114             # If the user is suspended because of a lack of payment the suspension is deactivated.
115             suspensions = Suspension.objects.filter(payment_id=self.id, user=user)
116             for suspension in suspensions:
117                 suspension.active = False
118                 suspension.save()
119 
120             if attendee:
121                 attendee[0].paid = True
122                 attendee[0].save()
123             else:
124                 Attendee.objects.create(event=self.content_object, user=user, paid=True)
125 
126     def handle_refund(self, host, payment_relation):
127         payment_relation.refunded = True
128         payment_relation.save()
129 
130         if self._is_type(AttendanceEvent):
131             self.content_object.notify_waiting_list(
132                 host=host, unattended_user=payment_relation.user)
133             Attendee.objects.get(event=self.content_object,
134                                  user=payment_relation.user).delete()
135 
136     def check_refund(self, payment_relation):
137         if self._is_type(AttendanceEvent):
138             attendance_event = self.content_object
139             if attendance_event.unattend_deadline < timezone.now():
140                 return False, _("Fristen for og melde seg av har utgått")
141             if len(Attendee.objects.filter(event=attendance_event, user=payment_relation.user)) == 0:
142                 return False, _("Du er ikke påmeldt dette arrangementet.")
143             if attendance_event.event.event_start < timezone.now():
144                 return False, _("Dette arrangementet har allerede startet.")
145 
146             return True, ''
147 
148         return False, 'Refund checks not implemented'
149 
150     def prices(self):
151         return self.paymentprice_set.all()
152 
153     def price(self):
154         # TODO implement group based pricing
155         if self.paymentprice_set.count() > 0:
156             return self.paymentprice_set.all()[0]
157         return None
158 
159     def _is_type(self, model_type):
160         return ContentType.objects.get_for_model(model_type) == self.content_type
161 
162     def __str__(self):
163         return self.description()
164 
165     class Meta(object):
166         unique_together = ('content_type', 'object_id')
167 
168         verbose_name = _("betaling")
169         verbose_name_plural = _("betalinger")
170 
171 
172 class PaymentPrice(models.Model):
173     payment = models.ForeignKey(Payment)
174     price = models.IntegerField(_("pris"))
175     description = models.CharField(max_length=128, null=True, blank=True)
176 
177     def __str__(self):
178         return self.description + " (" + str(self.price) + "kr)"
179 
180     class Meta(object):
181         verbose_name = _("pris")
182         verbose_name_plural = _("priser")
183 
184 
185 class PaymentRelation(models.Model):
186     payment = models.ForeignKey(Payment)
187     payment_price = models.ForeignKey(PaymentPrice)
188     user = models.ForeignKey(User)
189     datetime = models.DateTimeField(auto_now=True)
190     refunded = models.BooleanField(default=False)
191 
192     unique_id = models.CharField(max_length=128, null=True, blank=True)
193     stripe_id = models.CharField(max_length=128)
194 
195     def save(self, *args, **kwargs):
196         if not self.unique_id:
197             self.unique_id = str(uuid.uuid4())
198         super(PaymentRelation, self).save(*args, **kwargs)
199 
200     def __str__(self):
201         return self.payment.description() + " - " + str(self.user)
202 
203     class Meta(object):
204         verbose_name = _("betalingsrelasjon")
205         verbose_name_plural = _("betalingsrelasjoner")
206 
207 
208 class PaymentDelay(models.Model):
209     payment = models.ForeignKey(Payment)
210     user = models.ForeignKey(User)
211     valid_to = models.DateTimeField()
212 
213     active = models.BooleanField(default=True)
214 
215     def __str__(self):
216         return self.payment.description() + " - " + str(self.user)
217 
218     class Meta(object):
219         unique_together = ('payment', 'user')
220 
221         verbose_name = _('betalingsutsettelse')
222         verbose_name_plural = _('betalingsutsettelser')
223 
224 
225 class PaymentTransaction(models.Model):
226     user = models.ForeignKey(User)
227     amount = models.IntegerField(null=True, blank=True)
228     used_stripe = models.BooleanField(default=False)
229 
230     datetime = models.DateTimeField(auto_now=True)
231 
232     def __str__(self):
233         return str(self.user) + " - " + str(self.amount) + "(" + str(self.datetime) + ")"
234 
235     def save(self, *args, **kwargs):
236         if not self.pk:
237             self.user.saldo = self.user.saldo + self.amount
238 
239             if self.user.saldo < 0:
240                 raise NotAcceptable("Insufficient funds")
241 
242             self.user.save()
243         super(PaymentTransaction, self).save(*args, **kwargs)
244 
245     class Meta:
246         ordering = ['-datetime']
247         verbose_name = _('transaksjon')
248         verbose_name_plural = _('transaksjoner')
249
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/apps/payment/models.py b/apps/payment/models.py
--- a/apps/payment/models.py
+++ b/apps/payment/models.py
@@ -175,6 +175,8 @@
     description = models.CharField(max_length=128, null=True, blank=True)
 
     def __str__(self):
+        if not self.description:
+            return str(self.price) + "kr"
         return self.description + " (" + str(self.price) + "kr)"
 
     class Meta(object):

{"golden_diff": "diff --git a/apps/payment/models.py b/apps/payment/models.py\n--- a/apps/payment/models.py\n+++ b/apps/payment/models.py\n@@ -175,6 +175,8 @@\n     description = models.CharField(max_length=128, null=True, blank=True)\n \n     def __str__(self):\n+        if not self.description:\n+            return str(self.price) + \"kr\"\n         return self.description + \" (\" + str(self.price) + \"kr)\"\n \n     class Meta(object):\n", "issue": "PaymentPrice description is not required by manager but required for __str__\n## What kind of an issue is this?\r\n\r\n- [x] Bug report\r\n\r\n\r\n## What is the expected behaviour?\r\n\r\nThat you can create a PaymentPrice by following the guidelines, which are a required price and an optional description.\r\n\r\n## What is the current behaviour?\r\n\r\nBy creating a PaymentPrice with a required price but no description the system fails with the error message\r\n\r\n```\r\nTypeError at /admin/payment/payment/add/\r\nunsupported operand type(s) for +: 'NoneType' and 'str'\r\n```\r\n\r\n\r\n## How do you reproduce this problem? \r\n\r\n* Create an event with an attached attendance\r\n* Navigate to /admin/payment/payment/add/\r\n* Add a payment to the attendance event you created, without a description (but with a price)\r\n* The system crashes with the error message `unsupported operand type(s) for +: 'NoneType' and 'str'`\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\nimport uuid\n\nfrom django.conf import settings\nfrom django.contrib.contenttypes.fields import GenericForeignKey\nfrom django.contrib.contenttypes.models import ContentType\nfrom django.db import models\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext as _\nfrom rest_framework.exceptions import NotAcceptable\n\nfrom apps.events.models import AttendanceEvent, Attendee\nfrom apps.marks.models import Suspension\n\nUser = settings.AUTH_USER_MODEL\n\n\nclass Payment(models.Model):\n\n    TYPE_CHOICES = (\n        (1, _('Umiddelbar')),\n        (2, _('Frist')),\n        (3, _('Utsettelse')),\n    )\n\n    # Make sure these exist in settings if they are to be used.\n    STRIPE_KEY_CHOICES = (\n        ('arrkom', 'arrkom'),\n        ('prokom', 'prokom'),\n        ('trikom', 'trikom'),\n        ('fagkom', 'fagkom'),\n    )\n\n    content_type = models.ForeignKey(ContentType)\n    object_id = models.PositiveIntegerField()\n    content_object = GenericForeignKey()\n    stripe_key = models.CharField(\n        _('stripe key'),\n        max_length=10,\n        choices=STRIPE_KEY_CHOICES,\n        default=\"arrkom\"\n    )\n\n    payment_type = models.SmallIntegerField(_('type'), choices=TYPE_CHOICES)\n\n    # Optional fields depending on payment type\n    deadline = models.DateTimeField(_(\"frist\"), blank=True, null=True)\n    active = models.BooleanField(default=True)\n    delay = models.SmallIntegerField(_('utsettelse'), blank=True, null=True, default=2)\n\n    # For logging and history\n    added_date = models.DateTimeField(_(\"opprettet dato\"), auto_now=True)\n    changed_date = models.DateTimeField(auto_now=True, editable=False)\n    last_changed_by = models.ForeignKey(User, editable=False, null=True)  # Blank and null is temperarly\n\n    def paid_users(self):\n        return [payment_relation.user for payment_relation in self.paymentrelation_set.filter(refunded=False)]\n\n    def payment_delays(self):\n        return self.paymentdelay_set.filter(active=True)\n\n    def payment_delay_users(self):\n        return [payment_delay.user for payment_delay in self.payment_delays()]\n\n    def create_payment_delay(self, user, deadline):\n        payment_delays = self.paymentdelay_set.filter(payment=self, user=user)\n\n        if payment_delays:\n            for payment_delay in payment_delays:\n                payment_delay.valid_to = deadline\n                payment_delay.save()\n        else:\n            PaymentDelay.objects.create(payment=self, user=user, valid_to=deadline)\n\n    def description(self):\n        if self._is_type(AttendanceEvent):\n            return self.content_object.event.title\n\n    def get_receipt_description(self):\n        receipt_description = \"\"\n        description = [' '] * 30\n        temp = self.description()[0:25]\n        description[0:len(temp)+1] = list(temp)\n        for c in description:\n            receipt_description += c\n        return receipt_description\n\n    def responsible_mail(self):\n        if self._is_type(AttendanceEvent):\n            event_type = self.content_object.event.event_type\n            if event_type == 1 or event_type == 4:  # Sosialt & Utflukt\n                return settings.EMAIL_ARRKOM\n            elif event_type == 2:  # Bedpres\n                return settings.EMAIL_BEDKOM\n            elif event_type == 3:  # Kurs\n                return settings.EMAIL_FAGKOM\n            elif event_type == 5:  # Ekskursjon\n                return settings.EMAIL_EKSKOM\n            else:\n                return settings.DEFAULT_FROM_EMAIL\n        else:\n            return settings.DEFAULT_FROM_EMAIL\n\n    def handle_payment(self, user):\n        if self._is_type(AttendanceEvent):\n            attendee = Attendee.objects.filter(event=self.content_object, user=user)\n\n            # Delete payment delay objects for the user if there are any\n            delays = PaymentDelay.objects.filter(payment=self, user=user)\n            for delay in delays:\n                delay.delete()\n\n            # If the user is suspended because of a lack of payment the suspension is deactivated.\n            suspensions = Suspension.objects.filter(payment_id=self.id, user=user)\n            for suspension in suspensions:\n                suspension.active = False\n                suspension.save()\n\n            if attendee:\n                attendee[0].paid = True\n                attendee[0].save()\n            else:\n                Attendee.objects.create(event=self.content_object, user=user, paid=True)\n\n    def handle_refund(self, host, payment_relation):\n        payment_relation.refunded = True\n        payment_relation.save()\n\n        if self._is_type(AttendanceEvent):\n            self.content_object.notify_waiting_list(\n                host=host, unattended_user=payment_relation.user)\n            Attendee.objects.get(event=self.content_object,\n                                 user=payment_relation.user).delete()\n\n    def check_refund(self, payment_relation):\n        if self._is_type(AttendanceEvent):\n            attendance_event = self.content_object\n            if attendance_event.unattend_deadline < timezone.now():\n                return False, _(\"Fristen for og melde seg av har utg\u00e5tt\")\n            if len(Attendee.objects.filter(event=attendance_event, user=payment_relation.user)) == 0:\n                return False, _(\"Du er ikke p\u00e5meldt dette arrangementet.\")\n            if attendance_event.event.event_start < timezone.now():\n                return False, _(\"Dette arrangementet har allerede startet.\")\n\n            return True, ''\n\n        return False, 'Refund checks not implemented'\n\n    def prices(self):\n        return self.paymentprice_set.all()\n\n    def price(self):\n        # TODO implement group based pricing\n        if self.paymentprice_set.count() > 0:\n            return self.paymentprice_set.all()[0]\n        return None\n\n    def _is_type(self, model_type):\n        return ContentType.objects.get_for_model(model_type) == self.content_type\n\n    def __str__(self):\n        return self.description()\n\n    class Meta(object):\n        unique_together = ('content_type', 'object_id')\n\n        verbose_name = _(\"betaling\")\n        verbose_name_plural = _(\"betalinger\")\n\n\nclass PaymentPrice(models.Model):\n    payment = models.ForeignKey(Payment)\n    price = models.IntegerField(_(\"pris\"))\n    description = models.CharField(max_length=128, null=True, blank=True)\n\n    def __str__(self):\n        return self.description + \" (\" + str(self.price) + \"kr)\"\n\n    class Meta(object):\n        verbose_name = _(\"pris\")\n        verbose_name_plural = _(\"priser\")\n\n\nclass PaymentRelation(models.Model):\n    payment = models.ForeignKey(Payment)\n    payment_price = models.ForeignKey(PaymentPrice)\n    user = models.ForeignKey(User)\n    datetime = models.DateTimeField(auto_now=True)\n    refunded = models.BooleanField(default=False)\n\n    unique_id = models.CharField(max_length=128, null=True, blank=True)\n    stripe_id = models.CharField(max_length=128)\n\n    def save(self, *args, **kwargs):\n        if not self.unique_id:\n            self.unique_id = str(uuid.uuid4())\n        super(PaymentRelation, self).save(*args, **kwargs)\n\n    def __str__(self):\n        return self.payment.description() + \" - \" + str(self.user)\n\n    class Meta(object):\n        verbose_name = _(\"betalingsrelasjon\")\n        verbose_name_plural = _(\"betalingsrelasjoner\")\n\n\nclass PaymentDelay(models.Model):\n    payment = models.ForeignKey(Payment)\n    user = models.ForeignKey(User)\n    valid_to = models.DateTimeField()\n\n    active = models.BooleanField(default=True)\n\n    def __str__(self):\n        return self.payment.description() + \" - \" + str(self.user)\n\n    class Meta(object):\n        unique_together = ('payment', 'user')\n\n        verbose_name = _('betalingsutsettelse')\n        verbose_name_plural = _('betalingsutsettelser')\n\n\nclass PaymentTransaction(models.Model):\n    user = models.ForeignKey(User)\n    amount = models.IntegerField(null=True, blank=True)\n    used_stripe = models.BooleanField(default=False)\n\n    datetime = models.DateTimeField(auto_now=True)\n\n    def __str__(self):\n        return str(self.user) + \" - \" + str(self.amount) + \"(\" + str(self.datetime) + \")\"\n\n    def save(self, *args, **kwargs):\n        if not self.pk:\n            self.user.saldo = self.user.saldo + self.amount\n\n            if self.user.saldo < 0:\n                raise NotAcceptable(\"Insufficient funds\")\n\n            self.user.save()\n        super(PaymentTransaction, self).save(*args, **kwargs)\n\n    class Meta:\n        ordering = ['-datetime']\n        verbose_name = _('transaksjon')\n        verbose_name_plural = _('transaksjoner')\n", "path": "apps/payment/models.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\nimport uuid\n\nfrom django.conf import settings\nfrom django.contrib.contenttypes.fields import GenericForeignKey\nfrom django.contrib.contenttypes.models import ContentType\nfrom django.db import models\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext as _\nfrom rest_framework.exceptions import NotAcceptable\n\nfrom apps.events.models import AttendanceEvent, Attendee\nfrom apps.marks.models import Suspension\n\nUser = settings.AUTH_USER_MODEL\n\n\nclass Payment(models.Model):\n\n    TYPE_CHOICES = (\n        (1, _('Umiddelbar')),\n        (2, _('Frist')),\n        (3, _('Utsettelse')),\n    )\n\n    # Make sure these exist in settings if they are to be used.\n    STRIPE_KEY_CHOICES = (\n        ('arrkom', 'arrkom'),\n        ('prokom', 'prokom'),\n        ('trikom', 'trikom'),\n        ('fagkom', 'fagkom'),\n    )\n\n    content_type = models.ForeignKey(ContentType)\n    object_id = models.PositiveIntegerField()\n    content_object = GenericForeignKey()\n    stripe_key = models.CharField(\n        _('stripe key'),\n        max_length=10,\n        choices=STRIPE_KEY_CHOICES,\n        default=\"arrkom\"\n    )\n\n    payment_type = models.SmallIntegerField(_('type'), choices=TYPE_CHOICES)\n\n    # Optional fields depending on payment type\n    deadline = models.DateTimeField(_(\"frist\"), blank=True, null=True)\n    active = models.BooleanField(default=True)\n    delay = models.SmallIntegerField(_('utsettelse'), blank=True, null=True, default=2)\n\n    # For logging and history\n    added_date = models.DateTimeField(_(\"opprettet dato\"), auto_now=True)\n    changed_date = models.DateTimeField(auto_now=True, editable=False)\n    last_changed_by = models.ForeignKey(User, editable=False, null=True)  # Blank and null is temperarly\n\n    def paid_users(self):\n        return [payment_relation.user for payment_relation in self.paymentrelation_set.filter(refunded=False)]\n\n    def payment_delays(self):\n        return self.paymentdelay_set.filter(active=True)\n\n    def payment_delay_users(self):\n        return [payment_delay.user for payment_delay in self.payment_delays()]\n\n    def create_payment_delay(self, user, deadline):\n        payment_delays = self.paymentdelay_set.filter(payment=self, user=user)\n\n        if payment_delays:\n            for payment_delay in payment_delays:\n                payment_delay.valid_to = deadline\n                payment_delay.save()\n        else:\n            PaymentDelay.objects.create(payment=self, user=user, valid_to=deadline)\n\n    def description(self):\n        if self._is_type(AttendanceEvent):\n            return self.content_object.event.title\n\n    def get_receipt_description(self):\n        receipt_description = \"\"\n        description = [' '] * 30\n        temp = self.description()[0:25]\n        description[0:len(temp)+1] = list(temp)\n        for c in description:\n            receipt_description += c\n        return receipt_description\n\n    def responsible_mail(self):\n        if self._is_type(AttendanceEvent):\n            event_type = self.content_object.event.event_type\n            if event_type == 1 or event_type == 4:  # Sosialt & Utflukt\n                return settings.EMAIL_ARRKOM\n            elif event_type == 2:  # Bedpres\n                return settings.EMAIL_BEDKOM\n            elif event_type == 3:  # Kurs\n                return settings.EMAIL_FAGKOM\n            elif event_type == 5:  # Ekskursjon\n                return settings.EMAIL_EKSKOM\n            else:\n                return settings.DEFAULT_FROM_EMAIL\n        else:\n            return settings.DEFAULT_FROM_EMAIL\n\n    def handle_payment(self, user):\n        if self._is_type(AttendanceEvent):\n            attendee = Attendee.objects.filter(event=self.content_object, user=user)\n\n            # Delete payment delay objects for the user if there are any\n            delays = PaymentDelay.objects.filter(payment=self, user=user)\n            for delay in delays:\n                delay.delete()\n\n            # If the user is suspended because of a lack of payment the suspension is deactivated.\n            suspensions = Suspension.objects.filter(payment_id=self.id, user=user)\n            for suspension in suspensions:\n                suspension.active = False\n                suspension.save()\n\n            if attendee:\n                attendee[0].paid = True\n                attendee[0].save()\n            else:\n                Attendee.objects.create(event=self.content_object, user=user, paid=True)\n\n    def handle_refund(self, host, payment_relation):\n        payment_relation.refunded = True\n        payment_relation.save()\n\n        if self._is_type(AttendanceEvent):\n            self.content_object.notify_waiting_list(\n                host=host, unattended_user=payment_relation.user)\n            Attendee.objects.get(event=self.content_object,\n                                 user=payment_relation.user).delete()\n\n    def check_refund(self, payment_relation):\n        if self._is_type(AttendanceEvent):\n            attendance_event = self.content_object\n            if attendance_event.unattend_deadline < timezone.now():\n                return False, _(\"Fristen for og melde seg av har utg\u00e5tt\")\n            if len(Attendee.objects.filter(event=attendance_event, user=payment_relation.user)) == 0:\n                return False, _(\"Du er ikke p\u00e5meldt dette arrangementet.\")\n            if attendance_event.event.event_start < timezone.now():\n                return False, _(\"Dette arrangementet har allerede startet.\")\n\n            return True, ''\n\n        return False, 'Refund checks not implemented'\n\n    def prices(self):\n        return self.paymentprice_set.all()\n\n    def price(self):\n        # TODO implement group based pricing\n        if self.paymentprice_set.count() > 0:\n            return self.paymentprice_set.all()[0]\n        return None\n\n    def _is_type(self, model_type):\n        return ContentType.objects.get_for_model(model_type) == self.content_type\n\n    def __str__(self):\n        return self.description()\n\n    class Meta(object):\n        unique_together = ('content_type', 'object_id')\n\n        verbose_name = _(\"betaling\")\n        verbose_name_plural = _(\"betalinger\")\n\n\nclass PaymentPrice(models.Model):\n    payment = models.ForeignKey(Payment)\n    price = models.IntegerField(_(\"pris\"))\n    description = models.CharField(max_length=128, null=True, blank=True)\n\n    def __str__(self):\n        if not self.description:\n            return str(self.price) + \"kr\"\n        return self.description + \" (\" + str(self.price) + \"kr)\"\n\n    class Meta(object):\n        verbose_name = _(\"pris\")\n        verbose_name_plural = _(\"priser\")\n\n\nclass PaymentRelation(models.Model):\n    payment = models.ForeignKey(Payment)\n    payment_price = models.ForeignKey(PaymentPrice)\n    user = models.ForeignKey(User)\n    datetime = models.DateTimeField(auto_now=True)\n    refunded = models.BooleanField(default=False)\n\n    unique_id = models.CharField(max_length=128, null=True, blank=True)\n    stripe_id = models.CharField(max_length=128)\n\n    def save(self, *args, **kwargs):\n        if not self.unique_id:\n            self.unique_id = str(uuid.uuid4())\n        super(PaymentRelation, self).save(*args, **kwargs)\n\n    def __str__(self):\n        return self.payment.description() + \" - \" + str(self.user)\n\n    class Meta(object):\n        verbose_name = _(\"betalingsrelasjon\")\n        verbose_name_plural = _(\"betalingsrelasjoner\")\n\n\nclass PaymentDelay(models.Model):\n    payment = models.ForeignKey(Payment)\n    user = models.ForeignKey(User)\n    valid_to = models.DateTimeField()\n\n    active = models.BooleanField(default=True)\n\n    def __str__(self):\n        return self.payment.description() + \" - \" + str(self.user)\n\n    class Meta(object):\n        unique_together = ('payment', 'user')\n\n        verbose_name = _('betalingsutsettelse')\n        verbose_name_plural = _('betalingsutsettelser')\n\n\nclass PaymentTransaction(models.Model):\n    user = models.ForeignKey(User)\n    amount = models.IntegerField(null=True, blank=True)\n    used_stripe = models.BooleanField(default=False)\n\n    datetime = models.DateTimeField(auto_now=True)\n\n    def __str__(self):\n        return str(self.user) + \" - \" + str(self.amount) + \"(\" + str(self.datetime) + \")\"\n\n    def save(self, *args, **kwargs):\n        if not self.pk:\n            self.user.saldo = self.user.saldo + self.amount\n\n            if self.user.saldo < 0:\n                raise NotAcceptable(\"Insufficient funds\")\n\n            self.user.save()\n        super(PaymentTransaction, self).save(*args, **kwargs)\n\n    class Meta:\n        ordering = ['-datetime']\n        verbose_name = _('transaksjon')\n        verbose_name_plural = _('transaksjoner')\n", "path": "apps/payment/models.py"}]}