We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Dopisać tooltip z metadanymi na LetterDetailView
![zaznaczenie_418](https://cloud.githubusercontent.com/assets/3618479/9562630/74158af4-4e71-11e5-8c87-566c046f1840.png)
http://giodo.gov.pl/1520221/id_art/8813/j/pl/


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `feder/letters/logs/models.py`
Content:
```
1 import json
2 from collections import OrderedDict
3 
4 from django.db import models
5 from django.db.models import Count
6 from django.urls import reverse
7 from django.utils.encoding import python_2_unicode_compatible
8 from django.utils.translation import ugettext_lazy as _
9 from jsonfield import JSONField
10 from model_utils import Choices
11 from model_utils.models import TimeStampedModel
12 
13 from feder.cases.models import Case
14 from feder.letters.models import Letter
15 
16 STATUS = Choices(('open', _('Open')),
17                  ('ok', _('Delivered')),
18                  ('spambounce', _('Spam-bounce')),
19                  ('softbounce', _('Soft-bounce')),
20                  ('hardbounce', _('Hard-bounce')),
21                  ('dropped', _('Dropped')),
22                  ('deferred', _('Deferred')),
23                  ('unknown', _('Unknown'))
24                  )
25 
26 
27 class EmailQuerySet(models.QuerySet):
28     def with_logrecord_count(self):
29         return self.annotate(Count('logrecord'))
30 
31 
32 @python_2_unicode_compatible
33 class EmailLog(TimeStampedModel):
34     status = models.CharField(choices=STATUS, default=STATUS.unknown, max_length=20)
35     case = models.ForeignKey(Case, max_length=_("Case"))
36     letter = models.ForeignKey(Letter, max_length=_("Letter"), null=True, blank=True)
37     email_id = models.CharField(verbose_name=_("Message-ID"), max_length=255)
38     to = models.CharField(verbose_name=_("To"), max_length=255)
39     objects = EmailQuerySet.as_manager()
40 
41     def __str__(self):
42         return "Email #{} ({})".format(self.pk, self.email_id)
43 
44     def get_absolute_url(self):
45         return reverse('logs:detail', kwargs={'pk': self.pk})
46 
47     class Meta:
48         verbose_name = _("Email")
49         verbose_name_plural = _("Emails")
50         ordering = ['created', ]
51 
52 
53 class LogRecordQuerySet(models.QuerySet):
54     def parse_rows(self, rows):
55         skipped, saved = 0, 0
56         cases = dict(Letter.objects.values_list('case__email', 'case_id'))
57         letters = dict(Letter.objects.is_outgoing().values_list('message_id_header', 'id'))
58 
59         for row in rows:
60             if row['from'] not in cases:
61                 skipped += 1
62                 continue
63             log = LogRecord(data=row)
64             status = log.get_status()
65             letter = letters.get(row['message_id'], None)
66             obj, created = EmailLog.objects.get_or_create(case_id=cases[row['from']],
67                                                           email_id=row['id'],
68                                                           to=row['to'],
69                                                           defaults={'status': status,
70                                                                     'letter_id': letter})
71             if obj.status != status:
72                 obj.status = status
73                 obj.save(update_fields=['status'])
74             log.email = obj
75             log.save()
76             saved += 1
77         return (skipped, saved)
78 
79 
80 @python_2_unicode_compatible
81 class LogRecord(TimeStampedModel):
82     email = models.ForeignKey(EmailLog, verbose_name=_("Email"))
83     data = JSONField()
84     objects = LogRecordQuerySet.as_manager()
85 
86     def get_status(self):
87         status_list = OrderedDict(STATUS).keys()
88         for status in status_list:
89             time_name = '{}_time'.format(status)
90             desc_name = '{}_desc'.format(status)
91             if self.data.get(time_name, False) or self.data.get(desc_name, False):
92                 return status
93         return STATUS.unknown
94 
95     def pretty_json(self):
96         return json.dumps(self.data, indent=4)
97 
98     class Meta:
99         verbose_name = _("Log record")
100         verbose_name_plural = _("Log records")
101         ordering = ['created', ]
102 
103     def __str__(self):
104         return "Log #{} for email #{}".format(self.pk, self.email_id)
105
```
--- 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/feder/letters/logs/models.py b/feder/letters/logs/models.py
--- a/feder/letters/logs/models.py
+++ b/feder/letters/logs/models.py
@@ -33,7 +33,7 @@
 class EmailLog(TimeStampedModel):
     status = models.CharField(choices=STATUS, default=STATUS.unknown, max_length=20)
     case = models.ForeignKey(Case, max_length=_("Case"))
-    letter = models.ForeignKey(Letter, max_length=_("Letter"), null=True, blank=True)
+    letter = models.OneToOneField(Letter, max_length=_("Letter"), null=True, blank=True)
     email_id = models.CharField(verbose_name=_("Message-ID"), max_length=255)
     to = models.CharField(verbose_name=_("To"), max_length=255)
     objects = EmailQuerySet.as_manager()

{"golden_diff": "diff --git a/feder/letters/logs/models.py b/feder/letters/logs/models.py\n--- a/feder/letters/logs/models.py\n+++ b/feder/letters/logs/models.py\n@@ -33,7 +33,7 @@\n class EmailLog(TimeStampedModel):\n     status = models.CharField(choices=STATUS, default=STATUS.unknown, max_length=20)\n     case = models.ForeignKey(Case, max_length=_(\"Case\"))\n-    letter = models.ForeignKey(Letter, max_length=_(\"Letter\"), null=True, blank=True)\n+    letter = models.OneToOneField(Letter, max_length=_(\"Letter\"), null=True, blank=True)\n     email_id = models.CharField(verbose_name=_(\"Message-ID\"), max_length=255)\n     to = models.CharField(verbose_name=_(\"To\"), max_length=255)\n     objects = EmailQuerySet.as_manager()\n", "issue": "Dopisa\u0107 tooltip z metadanymi na LetterDetailView\n![zaznaczenie_418](https://cloud.githubusercontent.com/assets/3618479/9562630/74158af4-4e71-11e5-8c87-566c046f1840.png)\nhttp://giodo.gov.pl/1520221/id_art/8813/j/pl/\n\n", "before_files": [{"content": "import json\nfrom collections import OrderedDict\n\nfrom django.db import models\nfrom django.db.models import Count\nfrom django.urls import reverse\nfrom django.utils.encoding import python_2_unicode_compatible\nfrom django.utils.translation import ugettext_lazy as _\nfrom jsonfield import JSONField\nfrom model_utils import Choices\nfrom model_utils.models import TimeStampedModel\n\nfrom feder.cases.models import Case\nfrom feder.letters.models import Letter\n\nSTATUS = Choices(('open', _('Open')),\n                 ('ok', _('Delivered')),\n                 ('spambounce', _('Spam-bounce')),\n                 ('softbounce', _('Soft-bounce')),\n                 ('hardbounce', _('Hard-bounce')),\n                 ('dropped', _('Dropped')),\n                 ('deferred', _('Deferred')),\n                 ('unknown', _('Unknown'))\n                 )\n\n\nclass EmailQuerySet(models.QuerySet):\n    def with_logrecord_count(self):\n        return self.annotate(Count('logrecord'))\n\n\n@python_2_unicode_compatible\nclass EmailLog(TimeStampedModel):\n    status = models.CharField(choices=STATUS, default=STATUS.unknown, max_length=20)\n    case = models.ForeignKey(Case, max_length=_(\"Case\"))\n    letter = models.ForeignKey(Letter, max_length=_(\"Letter\"), null=True, blank=True)\n    email_id = models.CharField(verbose_name=_(\"Message-ID\"), max_length=255)\n    to = models.CharField(verbose_name=_(\"To\"), max_length=255)\n    objects = EmailQuerySet.as_manager()\n\n    def __str__(self):\n        return \"Email #{} ({})\".format(self.pk, self.email_id)\n\n    def get_absolute_url(self):\n        return reverse('logs:detail', kwargs={'pk': self.pk})\n\n    class Meta:\n        verbose_name = _(\"Email\")\n        verbose_name_plural = _(\"Emails\")\n        ordering = ['created', ]\n\n\nclass LogRecordQuerySet(models.QuerySet):\n    def parse_rows(self, rows):\n        skipped, saved = 0, 0\n        cases = dict(Letter.objects.values_list('case__email', 'case_id'))\n        letters = dict(Letter.objects.is_outgoing().values_list('message_id_header', 'id'))\n\n        for row in rows:\n            if row['from'] not in cases:\n                skipped += 1\n                continue\n            log = LogRecord(data=row)\n            status = log.get_status()\n            letter = letters.get(row['message_id'], None)\n            obj, created = EmailLog.objects.get_or_create(case_id=cases[row['from']],\n                                                          email_id=row['id'],\n                                                          to=row['to'],\n                                                          defaults={'status': status,\n                                                                    'letter_id': letter})\n            if obj.status != status:\n                obj.status = status\n                obj.save(update_fields=['status'])\n            log.email = obj\n            log.save()\n            saved += 1\n        return (skipped, saved)\n\n\n@python_2_unicode_compatible\nclass LogRecord(TimeStampedModel):\n    email = models.ForeignKey(EmailLog, verbose_name=_(\"Email\"))\n    data = JSONField()\n    objects = LogRecordQuerySet.as_manager()\n\n    def get_status(self):\n        status_list = OrderedDict(STATUS).keys()\n        for status in status_list:\n            time_name = '{}_time'.format(status)\n            desc_name = '{}_desc'.format(status)\n            if self.data.get(time_name, False) or self.data.get(desc_name, False):\n                return status\n        return STATUS.unknown\n\n    def pretty_json(self):\n        return json.dumps(self.data, indent=4)\n\n    class Meta:\n        verbose_name = _(\"Log record\")\n        verbose_name_plural = _(\"Log records\")\n        ordering = ['created', ]\n\n    def __str__(self):\n        return \"Log #{} for email #{}\".format(self.pk, self.email_id)\n", "path": "feder/letters/logs/models.py"}], "after_files": [{"content": "import json\nfrom collections import OrderedDict\n\nfrom django.db import models\nfrom django.db.models import Count\nfrom django.urls import reverse\nfrom django.utils.encoding import python_2_unicode_compatible\nfrom django.utils.translation import ugettext_lazy as _\nfrom jsonfield import JSONField\nfrom model_utils import Choices\nfrom model_utils.models import TimeStampedModel\n\nfrom feder.cases.models import Case\nfrom feder.letters.models import Letter\n\nSTATUS = Choices(('open', _('Open')),\n                 ('ok', _('Delivered')),\n                 ('spambounce', _('Spam-bounce')),\n                 ('softbounce', _('Soft-bounce')),\n                 ('hardbounce', _('Hard-bounce')),\n                 ('dropped', _('Dropped')),\n                 ('deferred', _('Deferred')),\n                 ('unknown', _('Unknown'))\n                 )\n\n\nclass EmailQuerySet(models.QuerySet):\n    def with_logrecord_count(self):\n        return self.annotate(Count('logrecord'))\n\n\n@python_2_unicode_compatible\nclass EmailLog(TimeStampedModel):\n    status = models.CharField(choices=STATUS, default=STATUS.unknown, max_length=20)\n    case = models.ForeignKey(Case, max_length=_(\"Case\"))\n    letter = models.OneToOneField(Letter, max_length=_(\"Letter\"), null=True, blank=True)\n    email_id = models.CharField(verbose_name=_(\"Message-ID\"), max_length=255)\n    to = models.CharField(verbose_name=_(\"To\"), max_length=255)\n    objects = EmailQuerySet.as_manager()\n\n    def __str__(self):\n        return \"Email #{} ({})\".format(self.pk, self.email_id)\n\n    def get_absolute_url(self):\n        return reverse('logs:detail', kwargs={'pk': self.pk})\n\n    class Meta:\n        verbose_name = _(\"Email\")\n        verbose_name_plural = _(\"Emails\")\n        ordering = ['created', ]\n\n\nclass LogRecordQuerySet(models.QuerySet):\n    def parse_rows(self, rows):\n        skipped, saved = 0, 0\n        cases = dict(Letter.objects.values_list('case__email', 'case_id'))\n        letters = dict(Letter.objects.is_outgoing().values_list('message_id_header', 'id'))\n\n        for row in rows:\n            if row['from'] not in cases:\n                skipped += 1\n                continue\n            log = LogRecord(data=row)\n            status = log.get_status()\n            letter = letters.get(row['message_id'], None)\n            obj, created = EmailLog.objects.get_or_create(case_id=cases[row['from']],\n                                                          email_id=row['id'],\n                                                          to=row['to'],\n                                                          defaults={'status': status,\n                                                                    'letter_id': letter})\n            if obj.status != status:\n                obj.status = status\n                obj.save(update_fields=['status'])\n            log.email = obj\n            log.save()\n            saved += 1\n        return (skipped, saved)\n\n\n@python_2_unicode_compatible\nclass LogRecord(TimeStampedModel):\n    email = models.ForeignKey(EmailLog, verbose_name=_(\"Email\"))\n    data = JSONField()\n    objects = LogRecordQuerySet.as_manager()\n\n    def get_status(self):\n        status_list = OrderedDict(STATUS).keys()\n        for status in status_list:\n            time_name = '{}_time'.format(status)\n            desc_name = '{}_desc'.format(status)\n            if self.data.get(time_name, False) or self.data.get(desc_name, False):\n                return status\n        return STATUS.unknown\n\n    def pretty_json(self):\n        return json.dumps(self.data, indent=4)\n\n    class Meta:\n        verbose_name = _(\"Log record\")\n        verbose_name_plural = _(\"Log records\")\n        ordering = ['created', ]\n\n    def __str__(self):\n        return \"Log #{} for email #{}\".format(self.pk, self.email_id)\n", "path": "feder/letters/logs/models.py"}]}