Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1379 part2 1377 unapproved list #15

Open
wants to merge 37 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c77e25c
extract zipfile inside zipfile in sample data lesson
sumandari May 17, 2021
d09aeb5
update unit test for download sample data lesson
sumandari May 17, 2021
0092fff
update unit test
sumandari May 17, 2021
7de9b96
fixed dockerfile for development and the documentation
Nov 23, 2021
547869c
fixed raising ValidationError in validate_email_address
sumandari Nov 26, 2021
79e0987
fixed typo flake8
sumandari Nov 26, 2021
bfab4ac
Merge pull request #1374 from sumandari/fix_dev_docker_and_readme
Nov 26, 2021
f4b45d3
Merge branch 'develop' of https://github.com/kartoza/prj.app into 137…
sumandari Nov 26, 2021
7f837e5
Merge pull request #1376 from sumandari/1372_fix_update_sustaining_me…
Dec 2, 2021
c1a2cb5
Merge pull request #1341 from sumandari/1328_lesson_extract_zip_in_zi…
Dec 2, 2021
613dbe7
added CertificateType model
sumandari Dec 3, 2021
a1c5b72
added admin class
sumandari Dec 3, 2021
3fb6b64
added CertificateType as foreign key in Certificate models and update…
sumandari Dec 3, 2021
af6b582
updated unittest
sumandari Dec 3, 2021
ec6763c
added project certificate_type
sumandari Dec 10, 2021
1f76a37
part#2: enable certification manager to manage certificate type list
sumandari Dec 10, 2021
935b99a
fixed typo flake8
sumandari Dec 11, 2021
45ca0e3
Part#3: added certificate_type in courseform
sumandari Dec 11, 2021
5c798d9
removed certificate_type in certificate model
sumandari Dec 11, 2021
22db5b5
updated queryset in courseform
sumandari Dec 16, 2021
2adf94e
Part#4 update template
sumandari Dec 16, 2021
5aeacd6
fixed typo flake8
sumandari Dec 16, 2021
85bd0b4
updated unit test and fix failed test
sumandari Dec 24, 2021
cf89c41
updated unit test and fix failed test
sumandari Dec 24, 2021
2cfa122
checklist app add and move order
sumandari Jan 17, 2022
32fce95
archive-activate checklist
sumandari Jan 20, 2022
db63d6e
remove unused files
sumandari Jan 20, 2022
0cf6479
renamed certificate_checklist.js
sumandari Jan 21, 2022
6a35524
fix pagination template
sumandari Jan 21, 2022
96977b0
add django-sorting-bootstrap dependency
sumandari Jan 21, 2022
a0680ee
updated pending organisations list
sumandari Jan 21, 2022
9c84388
added search
sumandari Jan 21, 2022
36730de
inifinite scroll
sumandari Jan 22, 2022
39c2904
fix infinite scroll content
sumandari Jan 22, 2022
646835f
add checklist on create and update page
sumandari Jan 27, 2022
06ce99e
add review
sumandari Jan 28, 2022
228563a
add response text field from applicant
sumandari Feb 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ When it's done, you can continue with this command:
Linux and MacOS:

```
cp docker-compose.override.example.yml docker-compose.override.yml
make build-devweb
make devweb
cp docker-compose.override.example.yml docker-compose.override.yml
```

In case you don't get some not installed packages, you can run this
Expand All @@ -54,6 +54,7 @@ repeatable steps:
Windows:

```
copy docker-compose.override.example.yml docker-compose.override.yml
make-devbuild.bat
make-devweb.bat
```
Expand Down
6 changes: 3 additions & 3 deletions deployment/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ MAINTAINER Tim Sutton<[email protected]>
#RUN ln -s /bin/true /sbin/initctl

# Pandoc needed to generate rst dumps, uic compressor needed for django-pipeline
RUN apt-get update -y; apt-get -y --force-yes install yui-compressor gettext
RUN apt-get update -y && apt-get -y --force-yes install yui-compressor gettext
RUN wget https://github.com/jgm/pandoc/releases/download/1.17.1/pandoc-1.17.1-2-amd64.deb
RUN dpkg -i pandoc-1.17.1-2-amd64.deb && rm pandoc-1.17.1-2-amd64.deb

Expand All @@ -18,7 +18,7 @@ ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1
ADD deployment/docker/REQUIREMENTS.txt /REQUIREMENTS.txt
ADD deployment/docker/uwsgi.conf /uwsgi.conf
ADD django_project /home/web/django_project
RUN pip install -r /REQUIREMENTS.txt
RUN pip install --upgrade pip && pip install -r /REQUIREMENTS.txt
RUN pip install uwsgi


Expand Down Expand Up @@ -50,7 +50,7 @@ RUN echo "export VISIBLE=now" >> /etc/profile
# End of cut & paste section

ADD deployment/docker/REQUIREMENTS-dev.txt /REQUIREMENTS-dev.txt
RUN pip install -r /REQUIREMENTS-dev.txt
RUN pip install --upgrade pip && pip install -r /REQUIREMENTS-dev.txt
ADD deployment/docker/bashrc /root/.bashrc

# --------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions deployment/docker/REQUIREMENTS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ pinax-notifications==5.0.3
pinax-templates==2.0.2
# rich text editor
django-tinymce==3.2.0
django-sorting-bootstrap==2.8.0
11 changes: 11 additions & 0 deletions django_project/certification/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.contrib.gis import admin
from simple_history.admin import SimpleHistoryAdmin
from certification.models.certificate import Certificate
from certification.models.certificate_type import CertificateType
from certification.models.course import Course
from certification.models.training_center import TrainingCenter
from certification.models.course_convener import CourseConvener
Expand Down Expand Up @@ -34,6 +35,15 @@ def queryset(self, request):
return query_set


class CertificateTypeAdmin(admin.ModelAdmin):
"""CertificateType admin model."""

list_display = ('name', 'wording', 'order')
list_editable = ('order', )
search_fields = ('name', 'wording')
ordering = ('order', )


class AttendeeAdmin(admin.ModelAdmin):
"""Attendee admin model."""
list_display = ('firstname', 'surname', 'email', 'certifying_organisation')
Expand Down Expand Up @@ -163,6 +173,7 @@ class StatusAdmin(admin.ModelAdmin):


admin.site.register(Certificate, CertificateAdmin)
admin.site.register(CertificateType, CertificateTypeAdmin)
admin.site.register(Attendee, AttendeeAdmin)
admin.site.register(Course, CourseAdmin)
admin.site.register(CourseType, CourseTypeAdmin)
Expand Down
Empty file.
7 changes: 7 additions & 0 deletions django_project/certification/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
from .models import (
CertifyingOrganisation,
CertificateType,
CourseConvener,
CourseType,
TrainingCenter,
Expand Down Expand Up @@ -303,6 +304,7 @@ class Meta:
'end_date',
'template_certificate',
'certifying_organisation',
'certificate_type',
)

def __init__(self, *args, **kwargs):
Expand All @@ -322,6 +324,7 @@ def __init__(self, *args, **kwargs):
Field('start_date', css_class='form-control'),
Field('end_date', css_class='form-control'),
Field('template_certificate', css_class='form-control'),
Field('certificate_type', css_class='form-control'),
)
)
self.helper.layout = layout
Expand All @@ -342,6 +345,10 @@ def __init__(self, *args, **kwargs):
self.certifying_organisation
self.fields['certifying_organisation'].widget = forms.HiddenInput()
self.helper.add_input(Submit('submit', 'Submit'))
self.fields['certificate_type'].queryset = \
CertificateType.objects.filter(
projectcertificatetype__project=
self.certifying_organisation.project)

def save(self, commit=True):
instance = super(CourseForm, self).save(commit=False)
Expand Down
34 changes: 34 additions & 0 deletions django_project/certification/migrations/0007_certificatetype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Generated by Django 2.2.18 on 2021-12-03 00:56

from django.db import migrations, models


def add_certification_type_as_existing_value(apps, schema_editor):
CertificateType = apps.get_model('certification', 'CertificateType')
CertificateType.objects.create(
name='attendance and completion',
wording='Has attended and completed the course:',
order=0
)


class Migration(migrations.Migration):

dependencies = [
('certification', '0006_auto_20210730_0615'),
]

operations = [
migrations.CreateModel(
name='CertificateType',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Certificate type.', max_length=200, unique=True)),
('description', models.TextField(blank=True, help_text='Certificate type description - 1000 characters limit.', max_length=1000, null=True)),
('wording', models.CharField(help_text='Wording that will be placed on certificate. e.g. "Has attended and completed".', max_length=500)),
('order', models.IntegerField(blank=True, null=True, unique=True)),
],
),

migrations.RunPython(add_certification_type_as_existing_value, reverse_code=migrations.RunPython.noop),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 2.2.18 on 2021-12-10 02:23

from django.db import migrations, models
import django.db.models.deletion

def create_existing_project_certificate_type(apps, schema_editor):
CertificateType = apps.get_model('certification', 'CertificateType')
ProjectCertificateType = apps.get_model('certification', 'ProjectCertificateType')
Project = apps.get_model('base', 'Project')
certificate_type = CertificateType.objects.filter(
name='attendance and completion').first()
projects = Project.objects.all()

for project in projects:
ProjectCertificateType.objects.create(
project=project,
certificate_type=certificate_type
)

class Migration(migrations.Migration):

dependencies = [
('base', '0006_auto_20210308_0244'),
('certification', '0007_certificatetype'),
]

operations = [
migrations.CreateModel(
name='ProjectCertificateType',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('certificate_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='certification.CertificateType')),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='base.Project')),
],
),

migrations.RunPython(create_existing_project_certificate_type, reverse_code=migrations.RunPython.noop),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 2.2.18 on 2021-12-10 08:31

from django.db import migrations, models
import django.db.models.deletion

def set_existing_certificate_type_value(apps, shcema_editor):
CertificateType = apps.get_model('certification', 'CertificateType')
Course = apps.get_model('certification', 'Course')
certificate_type = CertificateType.objects.filter(
name='attendance and completion').first()
courses = Course.objects.all()

for course in courses:
course.certificate_type = certificate_type
course.save(update_fields=['certificate_type'])


class Migration(migrations.Migration):

dependencies = [
('certification', '0008_projectcertificatetype'),
]

operations = [
migrations.AddField(
model_name='course',
name='certificate_type',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='certification.CertificateType'),
),

migrations.RunPython(set_existing_certificate_type_value, reverse_code=migrations.RunPython.noop),

migrations.AlterField(
model_name='course',
name='certificate_type',
field=models.ForeignKey(null=False, on_delete=django.db.models.deletion.PROTECT,
to='certification.CertificateType'),
preserve_default=False,
),

]
33 changes: 33 additions & 0 deletions django_project/certification/migrations/0010_auto_20220115_1805.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 2.2.18 on 2022-01-15 16:05

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('base', '0006_auto_20210308_0244'),
('certification', '0009_course_certificate_type'),
]

operations = [
migrations.AlterField(
model_name='course',
name='certificate_type',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='certification.CertificateType'),
),
migrations.CreateModel(
name='CertificateChecklist',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question', models.CharField(help_text='Question for certifying organisation applicant.', max_length=1000, unique=True)),
('sort_number', models.SmallIntegerField(blank=True, help_text='The order in which this category is listed within a project', null=True)),
('is_archived', models.BooleanField(default=False, help_text='Is this question archived?')),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='base.Project')),
],
options={
'unique_together': {('question', 'sort_number')},
},
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 2.2.18 on 2022-01-27 16:56

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('certification', '0010_auto_20220115_1805'),
]

operations = [
migrations.CreateModel(
name='CertifyingOrganisationChecklist',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_checked', models.BooleanField(help_text='Is the answer is yes or no', null=True)),
('certifying_organisation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='certification.CertifyingOrganisation')),
('question', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='certification.CertificateChecklist')),
],
options={
'unique_together': {('question', 'certifying_organisation')},
},
),
]
2 changes: 2 additions & 0 deletions django_project/certification/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@
from certification.models.course_attendee import *
from certification.models.course_type import *
from certification.models.course_convener import *
from certification.models.certificate_type import *
from certification.models.certificate import *
from certification.models.certificate_checklist import *
from certification.models.organisation_certificate import *
57 changes: 57 additions & 0 deletions django_project/certification/models/certificate_checklist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Certificate application model for certification apps."""

from django.db import models
from django.utils.translation import ugettext_lazy as _

from certification.models.certifying_organisation import CertifyingOrganisation


class CertificateChecklist(models.Model):
question = models.CharField(
help_text=_('Question for certifying organisation applicant.'),
max_length=1000,
unique=True,
)
Comment on lines +10 to +14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
question = models.CharField(
help_text=_('Question for certifying organisation applicant.'),
max_length=1000,
unique=True,
)
question = models.TextField(
help_text=_('Question for certifying organisation applicant.'), unique=True
)

TextField might be better used here, instead of CharField with a huge max_length. More info.

Comment on lines +10 to +14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
question = models.CharField(
help_text=_('Question for certifying organisation applicant.'),
max_length=1000,
unique=True,
)
question = models.TextField(
help_text=_('Question for certifying organisation applicant.'), unique=True
)

TextField might be better used here, instead of CharField with a huge max_length. More.

Comment on lines +10 to +14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
question = models.CharField(
help_text=_('Question for certifying organisation applicant.'),
max_length=1000,
unique=True,
)
question = models.TextField(
help_text=_('Question for certifying organisation applicant.'), unique=True
)

TextField might be better used here, instead of CharField with a huge max_length. More details.

Comment on lines +10 to +14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
question = models.CharField(
help_text=_('Question for certifying organisation applicant.'),
max_length=1000,
unique=True,
)
question = models.TextField(
help_text=_('Question for certifying organisation applicant.'), unique=True
)

TextField might be better used here, instead of CharField with a huge max_length. More info.

Comment on lines +10 to +14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
question = models.CharField(
help_text=_('Question for certifying organisation applicant.'),
max_length=1000,
unique=True,
)
question = models.TextField(
help_text=_('Question for certifying organisation applicant.'), unique=True
)

TextField might be better used here, instead of CharField with a huge max_length. Read more.

Comment on lines +10 to +14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
question = models.CharField(
help_text=_('Question for certifying organisation applicant.'),
max_length=1000,
unique=True,
)
question = models.TextField(
help_text=_('Question for certifying organisation applicant.'), unique=True
)

TextField might be better used here, instead of CharField with a huge max_length. Read more.

sort_number = models.SmallIntegerField(
help_text=_(
'The order in which this category is listed within a '
'project'),
blank=True,
null=True
)
is_archived = models.BooleanField(
help_text=_('Is this question archived?'),
default=False
)
project = models.ForeignKey('base.Project', on_delete=models.CASCADE)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. More.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. More info.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. Explained here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. More info.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. More info.


class Meta:
unique_together = (
('question', 'sort_number'),
)

def __str__(self):
return f'[{self.project.name}] {self.question}'


class CertifyingOrganisationChecklist(models.Model):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, with an explicit related_name would be better.

question = models.ForeignKey(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. Explained here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, with an explicit related_name would be better.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, with an explicit related_name would be better.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, with an explicit related_name would be better.

CertificateChecklist,
on_delete=models.PROTECT
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, with an explicit related_name would be better.

certifying_organisation = models.ForeignKey(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, with an explicit related_name would be better.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, with an explicit related_name would be better.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, with an explicit related_name would be better.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, with an explicit related_name would be better.

CertifyingOrganisation,
on_delete=models.CASCADE
)
is_checked = models.BooleanField(
help_text=_('Is the answer is yes or no'),
null=True
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, consider using a TextField.

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". More info.


class Meta:
unique_together = (
('question', 'certifying_organisation'),
)

def __str__(self):
return f'{self.is_checked}'
Loading