internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: kartoza/prj.app

Issue:
Negative credits
![image](https://user-images.githubusercontent.com/9982061/63650352-1ed08480-c74a-11e9-932f-73e0fb06a807.png)
Should this be possible?



Discussion:
hi @Geogoeroe currently yes, so you can issue as many certificates as you need and when your credits is not sufficient, you'll get negative credits. When your credits are not sufficient, you can only issue the certificate but cannot print it. But I think I'm going to change the logic so that it won't go negative.

Resolving patch:
diff --git a/django_project/certification/forms.py b/django_project/certification/forms.py
--- a/django_project/certification/forms.py
+++ b/django_project/certification/forms.py
@@ -6,6 +6,7 @@
 from django.contrib.gis import forms as geoforms
 from django.contrib.gis import gdal
 from django.contrib.gis.forms.widgets import BaseGeometryWidget
+from django.core.exceptions import ValidationError
 from crispy_forms.helper import FormHelper
 from crispy_forms.layout import (
     Layout,
@@ -439,6 +440,19 @@ def __init__(self, *args, **kwargs):
         self.fields['is_paid'].widget = forms.HiddenInput()
         self.helper.add_input(Submit('submit', 'Issue Certificate'))
 
+    def clean(self):
+        clean_data = self.cleaned_data
+        organisation = self.course.certifying_organisation
+
+        remaining_credits = \
+            organisation.organisation_credits - \
+            organisation.project.certificate_credit
+
+        if remaining_credits < 0:
+            raise ValidationError("Insufficient credits")
+
+        return clean_data
+
     def save(self, commit=True):
         instance = super(CertificateForm, self).save(commit=False)
         instance.author = self.user


Test patch:
Repository: kartoza/prj.app

Issue:
Improve certificate
The font should be the same and the spaces should be even


Discussion:

Resolving patch:
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -327,10 +327,7 @@ def generate_pdf(
     page.setFont('Times-Bold', 26)
     page.drawCentredString(center, 480, 'Certificate of Completion')
 
-    try:
-        page.setFont('Noto-bold', 26)
-    except KeyError:
-        page.setFont('Times-Bold', 26)
+    page.setFont('Times-Bold', 26)
 
     page.drawCentredString(
         center, 400, '%s %s' % (
@@ -341,7 +338,7 @@ def generate_pdf(
         center, 370, 'Has attended and completed the course:')
     page.setFont('Times-Bold', 20)
     page.drawCentredString(
-            center, 350, course.course_type.name.encode('utf-8'))
+            center, 335, course.course_type.name.encode('utf-8'))
     page.setFont('Times-Roman', 16)
     page.drawCentredString(
         center, 300, 'With a trained competence in:')
@@ -817,7 +814,7 @@ class DummyCertificate(object):
     """Dummy object for preview certificate."""
 
     def __init__(self, course, attendee, project):
-        self.certificateID = '{}-1'.format(project.name)
+        self.certificateID = '{}-DEMO'.format(project.name)
         self.course = course
         self.attendee = attendee
 


Test patch:
Repository: kartoza/prj.app

Issue:
Please include project name in certifying org admin
<img width="895" alt="image" src="https://user-images.githubusercontent.com/178003/67474466-6ab98000-f64c-11e9-8a69-95e12e8bd404.png">


We have two Kartoza entries there - one for InaSAFE and one for QGIS - I nearly deleted the first not realising it was for InaSAFE


Discussion:

Resolving patch:
diff --git a/django_project/certification/admin.py b/django_project/certification/admin.py
--- a/django_project/certification/admin.py
+++ b/django_project/certification/admin.py
@@ -141,7 +141,7 @@ class CertifyingOrganisationAdmin(SimpleHistoryAdmin):
 
     filter_horizontal = ('organisation_owners',)
     search_fields = ['name']
-    list_display = ('name', 'country', 'approved', 'rejected')
+    list_display = ('name', 'project', 'country', 'approved', 'rejected')
     list_filter = ('country', 'approved', 'rejected', 'status')
     inlines = (CertifyingOrganisationCertificateAdminInline, )
     history_list_display = ['status', 'remarks']


Test patch:
Repository: kartoza/prj.app

Issue:
Lesson number when using page 2
On this page, sections are from 1 to 10:
http://changelog.qgis.org/en/qgis/section/list/?page=1

If I go to page 2, I expect to start at 11, but it's starting again at 1:
http://changelog.qgis.org/en/qgis/section/list/?page=2

A minor issue ;-)


Discussion:
Thanks @Gustry - @ann26 will you take care of this?
will do @timlinux 

Resolving patch:
diff --git a/django_project/lesson/views/worksheet.py b/django_project/lesson/views/worksheet.py
--- a/django_project/lesson/views/worksheet.py
+++ b/django_project/lesson/views/worksheet.py
@@ -420,9 +420,33 @@ def get_context_data(pk):
 
     s = StringIO.StringIO()
     zf = zipfile.ZipFile(s, "w")
+    initial_numbering = ''
+    final_numbering = ''
 
     for pk in worksheets:
         numbering = worksheets[pk]
+        array_numbering = numbering.split('.')
+
+        if initial_numbering == '':
+            initial_numbering = numbering
+        else:
+            array_initial_numbering = initial_numbering.split('.')
+            if int(array_numbering[0]) < int(array_initial_numbering[0]):
+                initial_numbering = numbering
+            elif int(array_numbering[0]) == int(array_initial_numbering[0]):
+                if int(array_numbering[1]) < int(array_initial_numbering[1]):
+                    initial_numbering = numbering
+
+        if final_numbering == '':
+            final_numbering = numbering
+        else:
+            array_final_numbering = final_numbering.split('.')
+            if int(array_numbering[0]) > int(array_final_numbering[0]):
+                final_numbering = numbering
+            elif int(array_numbering[0]) == int(array_final_numbering[0]):
+                if int(array_numbering[1]) > int(array_final_numbering[1]):
+                    final_numbering = numbering
+
         pk = int(pk)
         worksheet = Worksheet.objects.get(pk=pk)
         pdf_title = '{}. {}'.format(numbering, worksheet.module.encode("utf8"))
@@ -462,9 +486,18 @@ def get_context_data(pk):
 
     zf.close()
 
+    downloaded_module = ''
+    if len(worksheets) > 0:
+        if len(worksheets) == 1:
+            downloaded_module = 'module {}'.format(initial_numbering)
+        else:
+            downloaded_module = 'module {} to {}'.format(
+                initial_numbering,
+                final_numbering)
+
     zip_response = HttpResponse(
         s.getvalue(), content_type="application/x-zip-compressed")
     zip_response['Content-Disposition'] = \
-        'attachment; filename={}-worksheet.zip'.format(
-            project.name.encode('utf8'))
+        'attachment; filename={}-worksheet {}.zip'.format(
+            project.name.encode('utf8'), downloaded_module)
     return zip_response


Test patch:
Repository: kartoza/prj.app

Issue:
500 error printing certificate
http://sentry.kartoza.com/sentry/projecta/issues/1727/

We have a problem with a new attendee and its certificate:

Alfredo González Fernández

http://changelog.qgis.org/en/qgis/certifyingorganisation/qgis-mappinggis/course/qgis_master-en-sistemas-de-informacion-geografica_2016-12-01-2018-05-29/print/1133/ 

The page with the verification is correct:
http://changelog.qgis.org/en/qgis/certificate/QGIS-990/  

Thanks for your help.



Discussion:

Resolving patch:
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -344,7 +344,7 @@ def generate_pdf(
         center, 300, 'With a trained competence in:')
     page.setFont('Times-Bold', 14)
     page.drawCentredString(
-        center, 280, '{}'.format(course.trained_competence))
+        center, 280, '{}'.format(course.trained_competence.encode('utf-8')))
     page.setFont('Times-Roman', 16)
     page.drawCentredString(
         center, 250, '{}'.format(course_duration))


Test patch:
Repository: kartoza/prj.app

Issue:
Problem with some strings in certificates
I have tried to issue a certificate but it appears with the updated website, there is an issue with the strings:
![image](https://user-images.githubusercontent.com/2649047/73525076-541e8400-4406-11ea-84e7-738542b3c279.png)



Discussion:

Resolving patch:
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -248,20 +248,20 @@ def generate_pdf(
     center = height * 0.5
     convener_name = \
         '{} {}'.format(
-            course.course_convener.user.first_name.encode('utf-8'),
-            course.course_convener.user.last_name.encode('utf-8'))
+            course.course_convener.user.first_name,
+            course.course_convener.user.last_name)
 
     if course.course_convener.title:
         convener_name = \
             '{} {}'.format(
-                course.course_convener.title.encode('utf-8'),
+                course.course_convener.title,
                 convener_name)
 
     if course.course_convener.degree:
         convener_name = \
             '{}, {}'.format(
                 convener_name,
-                course.course_convener.degree.encode('utf-8'))
+                course.course_convener.degree)
 
     course_duration = \
         'From {} {} {} to {} {} {}'.format(
@@ -337,20 +337,20 @@ def generate_pdf(
 
     page.drawCentredString(
         center, 400, '%s %s' % (
-            attendee.firstname.encode('utf-8'),
-            attendee.surname.encode('utf-8')))
+            attendee.firstname,
+            attendee.surname))
     page.setFont('Times-Roman', 16)
     page.drawCentredString(
         center, 370, 'Has attended and completed the course:')
     page.setFont('Times-Bold', 20)
     page.drawCentredString(
-            center, 335, course.course_type.name.encode('utf-8'))
+            center, 335, course.course_type.name)
     page.setFont('Times-Roman', 16)
     page.drawCentredString(
         center, 300, 'With a trained competence in:')
     page.setFont('Times-Bold', 14)
     page.drawCentredString(
-        center, 280, '{}'.format(course.trained_competence.encode('utf-8')))
+        center, 280, '{}'.format(course.trained_competence))
     page.setFont('Times-Roman', 16)
     page.drawCentredString(
         center, 250, '{}'.format(course_duration))
@@ -383,8 +383,8 @@ def generate_pdf(
         page.drawCentredString(
             (margin_left + 150), (margin_bottom + 60),
             '{} {}'.format(
-                project.project_representative.first_name.encode('utf-8'),
-                project.project_representative.last_name.encode('utf-8')))
+                project.project_representative.first_name,
+                project.project_representative.last_name))
     page.drawCentredString(
         (margin_right - 150), (margin_bottom + 60),
         '{}'.format(convener_name))


Test patch:
Repository: kartoza/prj.app

Issue:
Bulk attendee upload is broken
I am gettting an error uploading attendees using a CSV. I have done it successfully in the past using the same format CSV. For now, I have attended the participants manually.

Attached is my upload csv with the emails replaced with test@test.com to preserve privacy.

[attendees.txt](https://github.com/kartoza/prj.app/files/4202985/attendees.txt)



Discussion:
@ann26 can you take a look? It is probably a side effect of our python / django update.

Resolving patch:
diff --git a/django_project/certification/views/attendee.py b/django_project/certification/views/attendee.py
--- a/django_project/certification/views/attendee.py
+++ b/django_project/certification/views/attendee.py
@@ -1,4 +1,5 @@
 # coding=utf-8
+import io
 import csv
 from django.db import transaction
 from django.urls import reverse
@@ -171,11 +172,13 @@ def post(self, request, *args, **kwargs):
         form_class = self.get_form_class()
         form = self.get_form(form_class)
         attendees_file = request.FILES.get('file')
+        attendees_file.seek(0)
         course = Course.objects.get(slug=self.slug)
         if form.is_valid():
             if attendees_file:
-                reader = csv.reader(attendees_file, delimiter=',')
-                next(reader)
+                reader = csv.DictReader(
+                    io.StringIO(attendees_file.read().decode('utf-8'))
+                )
                 attendee_count = 0
                 course_attendee_count = 0
                 for row in reader:
@@ -183,9 +186,9 @@ def post(self, request, *args, **kwargs):
                     # already exists and if they do, just add them to the
                     # course
                     attendee = Attendee(
-                        firstname=row[0],
-                        surname=row[1],
-                        email=row[2],
+                        firstname=row['First Name'],
+                        surname=row['Surname'],
+                        email=row['Email'],
                         certifying_organisation=self.certifying_organisation,
                         author=self.request.user,
                     )


Test patch:
Repository: kartoza/prj.app

Issue:
Generated certificate special characters issues for course convener
The generated certificates support special characters except for the course convener (probably other font).
See:
[wrong_characters.pdf](https://github.com/kartoza/prj.app/files/3640982/wrong_characters.pdf)

I manually edited the certificates to bypass this.
Maybe changing the font of the course convener would be a better solution?


Discussion:
Thanks for the report @tudorbarascu . Can you look at this @ann26 ? 
This is a general problem; see also:
![problem](https://user-images.githubusercontent.com/3179646/73171146-b88ccb00-4108-11ea-9ca8-8bdce9443e50.png)
and
![problem1](https://user-images.githubusercontent.com/3179646/73171131-b0349000-4108-11ea-8112-bef1faae3410.png)

Resolving patch:
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -169,24 +169,20 @@ def get_context_data(self, **kwargs):
             certificate = context['certificate']
             convener_name = \
                 '{} {}'.format(
-                    certificate.course.course_convener.user.first_name.encode(
-                        'utf-8'),
-                    certificate.course.course_convener.user.last_name.encode(
-                        'utf-8'))
+                    certificate.course.course_convener.user.first_name,
+                    certificate.course.course_convener.user.last_name)
 
             if certificate.course.course_convener.title:
                 convener_name = \
                     '{} {}'.format(
-                        certificate.course.course_convener.title.encode(
-                            'utf-8'),
+                        certificate.course.course_convener.title,
                         convener_name)
 
             if certificate.course.course_convener.degree:
                 convener_name = \
                     '{}, {}'.format(
                         convener_name,
-                        certificate.course.course_convener.degree.encode(
-                            'utf-8'))
+                        certificate.course.course_convener.degree)
 
             context['convener_name'] = convener_name
         context['project_slug'] = self.project_slug


Test patch:
Repository: kartoza/prj.app

Issue:
Generated certificate special characters issues for course convener
The generated certificates support special characters except for the course convener (probably other font).
See:
[wrong_characters.pdf](https://github.com/kartoza/prj.app/files/3640982/wrong_characters.pdf)

I manually edited the certificates to bypass this.
Maybe changing the font of the course convener would be a better solution?


Discussion:
Thanks for the report @tudorbarascu . Can you look at this @ann26 ? 
This is a general problem; see also:
![problem](https://user-images.githubusercontent.com/3179646/73171146-b88ccb00-4108-11ea-9ca8-8bdce9443e50.png)
and
![problem1](https://user-images.githubusercontent.com/3179646/73171131-b0349000-4108-11ea-8112-bef1faae3410.png)
hi @tudorbarascu sorry for the long wait, I have fixed it, please try again. Also should you find your previous certificates with wrong characters please regenerate the certificate using this button as shown in figure below:
![Screenshot from 2020-02-17 16-25-11](https://user-images.githubusercontent.com/26101337/74641830-8bca5180-51a4-11ea-8dba-f7f42d4b31e7.png)

@ann26 Thanks a lot! I checked and the issue is solved only for the verifying workflow. For the pdf's, although I regenerated them it's still an issue. Am I doing something wrong?
hi @tudorbarascu could you give me the url and the attendee where the pdf is still not working?
Sure! https://changelog.qgis.org/en/qgis/certifyingorganisation/qgis-qtibia-engineering/course/qgis_waterwastewater-workflows-gis-databases-telemetry-hydraulical-modelling_2020-01-20-2020-01-24/print/961/  The course convener name is the problem, not the attendee name. Thank you again for taking care of this.

Resolving patch:
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -242,7 +242,7 @@ def generate_pdf(
             font_folder, 'Times New Roman 400.ttf')
         pdfmetrics.registerFont(TTFont('Noto-Bold', bold_ttf_file))
         pdfmetrics.registerFont(TTFont('Noto-Regular', regular_ttf_file))
-    except TTFError:
+    except (TTFError, KeyError):
         pass
 
     page = canvas.Canvas(pathname, pagesize=landscape(A4))
@@ -380,7 +380,7 @@ def generate_pdf(
             width=100, height=70, preserveAspectRatio=True, anchor='s',
             mask='auto')
 
-    page.setFont('Times-Italic', 12)
+    page.setFont('Noto-Regular', 12)
     if project.project_representative:
         page.drawCentredString(
             (margin_left + 150), (margin_bottom + 60),


Test patch:
Repository: kartoza/prj.app

Issue:
preview certificate is not working
from a user:

I'll be doing my first QGIS Training in the Philippines next month and was trying out using certificate templates in Projecta to create more personalized certificates for my attendees.

Previously, I was able to preview custom certificate templates by following the instructions here: https://changelog.qgis.org/en/qgis/about/.

But now, whenever I try to use a custom template, I get an error 500 like the one below:
![image](https://user-images.githubusercontent.com/26101337/74819975-cf06fa80-5333-11ea-9325-89a5edb2a55b.png)

I've tried this with different images -- transparent, all-white, etc. -- but the result is the same. Previewing a certificate without a template works though.




Discussion:

Resolving patch:
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -1,7 +1,8 @@
 # coding=utf-8
 
+import base64
 import datetime
-from io import StringIO, BytesIO
+from io import BytesIO
 import os
 import zipfile
 from PIL import Image
@@ -854,8 +855,9 @@ def preview_certificate(request, **kwargs):
         trained_competence = request.POST.get('trained_competence', '')
         if 'base64' in raw_image:
             image_data = re.sub('^data:image/.+;base64,', '',
-                                raw_image).decode('base64')
-            template_certificate = Image.open(StringIO(image_data))
+                                raw_image)
+            decoded_image = base64.b64decode(image_data.encode('utf-8'))
+            template_certificate = Image.open(BytesIO(decoded_image))
         else:
             template_certificate = None
 


Test patch:
Repository: kartoza/prj.app

Issue:
Email notifications still show kartoza.com 
The web site domain should be used for links etc. in emails that are sent out.


>Thank you for your application to become a sustaining member of QGIS.
>Your application will be reviewed by our admin team who will respond as soon as they can.
>If you have any queries regarding your application process please contact a.neumann@carto.net.
>You will receive an automated email once your application has been reviewed.
>If your membership is approved you can go back to the sustaining member web page to manage your subscription.

>Thank you for supporting our project!

>Best regards,

>The team.

>This is an auto-generated email from http://changelog.kartoza.com. Please do not reply to this email.
>To change how you receive notifications, please go to >http://changelog.kartoza.com/notifications/settings/


Discussion:

Resolving patch:
diff --git a/django_project/changes/admin.py b/django_project/changes/admin.py
--- a/django_project/changes/admin.py
+++ b/django_project/changes/admin.py
@@ -77,6 +77,7 @@ class SponsorAdmin(reversion.admin.VersionAdmin):
     """Sponsor admin model."""
 
     list_display = ['__unicode__', 'project']
+    search_fields = ['name']
 
     def queryset(self, request):
         """Ensure we use the correct manager.
diff --git a/django_project/changes/views/sustaining_member.py b/django_project/changes/views/sustaining_member.py
--- a/django_project/changes/views/sustaining_member.py
+++ b/django_project/changes/views/sustaining_member.py
@@ -120,6 +120,7 @@ def send_notification(self, sustaining_member, sponsorship_managers):
             extra_context={
                 'sustaining_member': sustaining_member,
                 'sustaining_member_manager': sponsorship_managers[0],
+                'active_site': self.request.get_host()
             },
             request_user=self.request.user
         )
@@ -334,6 +335,7 @@ def form_valid(self, form):
                 label=NOTICE_SUSTAINING_MEMBER_UPDATED,
                 extra_context={
                     'sustaining_member': self.form_object,
+                    'active_site': self.request.get_host()
                 },
                 request_user=self.request.user
             )
@@ -533,7 +535,8 @@ def form_valid(self, form):
                     'date_start': self.object.start_date.strftime(
                         "%B %d, %Y"),
                     'date_end': self.object.end_date.strftime(
-                        "%B %d, %Y")
+                        "%B %d, %Y"),
+                    'active_site': self.request.get_host()
                 })
             self.object.save()
 
@@ -743,6 +746,7 @@ def form_valid(self, form):
                         year=self.object.start_date.year + period_end
                     ).strftime(
                         "%B %d, %Y"),
+                    'active_site': self.request.get_host()
                 },
                 request_user=self.request.user
             )


Test patch: