From 9ceae5ab55f9c09db3cd2fbe3953e207408a08a4 Mon Sep 17 00:00:00 2001 From: Domenico Date: Mon, 16 Aug 2021 11:19:05 -0500 Subject: [PATCH 01/39] FAM - reference number on db --- src/etools/applications/audit/exports.py | 9 ++--- .../commands/update_audit_permissions.py | 2 +- .../0019_engagement_users_notified.py | 2 +- .../0022_engagement_reference_number.py | 40 +++++++++++++++++++ src/etools/applications/audit/models.py | 34 +++++++++++----- .../engagement-action_point_assigned.py | 4 +- .../audit/serializers/engagement.py | 9 +++-- .../applications/audit/serializers/export.py | 6 +-- src/etools/applications/audit/signals.py | 2 +- .../audit/templates/audit/engagement_pdf.html | 2 +- src/etools/applications/audit/views.py | 6 ++- 11 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 src/etools/applications/audit/migrations/0022_engagement_reference_number.py diff --git a/src/etools/applications/audit/exports.py b/src/etools/applications/audit/exports.py index 8999581c1a..8e7faa7528 100644 --- a/src/etools/applications/audit/exports.py +++ b/src/etools/applications/audit/exports.py @@ -1,4 +1,3 @@ - import itertools from collections import OrderedDict @@ -28,7 +27,7 @@ class EngagementCSVRenderer(BaseCSVRenderer): class SpotCheckDetailCSVRenderer(BaseCSVRenderer): labels = OrderedDict(( - ('unique_id', 'Unique ID'), + ('reference_number', 'Unique ID'), ('link', 'Hyperlink'), ('auditor', 'Auditor or Staff Assigned'), ('partner', 'IP'), @@ -49,7 +48,7 @@ class AuditDetailCSVRenderer(BaseCSVRenderer): @property def labels(self): labels = OrderedDict(( - ('unique_id', 'Unique ID'), + ('reference_number', 'Unique ID'), ('link', 'Hyperlink'), ('auditor', 'Auditor or Staff Assigned'), ('partner', 'IP'), @@ -83,7 +82,7 @@ class MicroAssessmentDetailCSVRenderer(BaseCSVRenderer): @property def labels(self): labels = OrderedDict(( - ('unique_id', 'Unique ID'), + ('reference_number', 'Unique ID'), ('link', 'Hyperlink'), ('auditor', 'Auditor or Staff Assigned'), ('partner', 'IP'), @@ -115,7 +114,7 @@ def header(self): class SpecialAuditDetailCSVRenderer(BaseCSVRenderer): labels = OrderedDict(( - ('unique_id', 'Unique ID'), + ('reference_number', 'Unique ID'), ('link', 'Hyperlink'), ('auditor', 'Auditor or Staff Assigned'), ('partner', 'IP'), diff --git a/src/etools/applications/audit/management/commands/update_audit_permissions.py b/src/etools/applications/audit/management/commands/update_audit_permissions.py index 1ee8d96890..cd571b7dd5 100644 --- a/src/etools/applications/audit/management/commands/update_audit_permissions.py +++ b/src/etools/applications/audit/management/commands/update_audit_permissions.py @@ -55,7 +55,7 @@ class Command(BaseCommand): action_points_editors = [focal_point, action_point_author, action_point_assignee, action_point_assigned_by] engagement_overview_read_block = [ - 'audit.engagement.unique_id', + 'audit.engagement.reference_number', 'audit.engagement.status', 'audit.engagement.status_date', diff --git a/src/etools/applications/audit/migrations/0019_engagement_users_notified.py b/src/etools/applications/audit/migrations/0019_engagement_users_notified.py index b0ca1e1877..4c5a58e645 100644 --- a/src/etools/applications/audit/migrations/0019_engagement_users_notified.py +++ b/src/etools/applications/audit/migrations/0019_engagement_users_notified.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('users', '0012_auto_20190513_1804'), ('audit', '0018_auto_20191008_2235'), ] diff --git a/src/etools/applications/audit/migrations/0022_engagement_reference_number.py b/src/etools/applications/audit/migrations/0022_engagement_reference_number.py new file mode 100644 index 0000000000..95efa18b9b --- /dev/null +++ b/src/etools/applications/audit/migrations/0022_engagement_reference_number.py @@ -0,0 +1,40 @@ +# Generated by Django 2.2.3 on 2019-08-14 12:17 + +from django.db import connection, migrations, models + + +def set_reference_number(apps, schema_editor): + Country = apps.get_model("users", "country") + Engagement = apps.get_model("audit", "engagement") + country = Country.objects.get( + schema_name=connection.tenant.schema_name, + ) + for engagement in Engagement.objects.all(): + if engagement.engagement_type == engagement.TYPES.audit: + engagement_code = 'a' + else: + engagement_code = engagement.engagement_type + engagement.reference_number = '{}/{}/{}/{}/{}'.format( + country.country_short_code, + engagement.partner.name[:5], + engagement_code.upper(), + engagement.created.year, + engagement.pk + ) + engagement.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('audit', '0021_auto_20200729_2123'), + ] + + operations = [ + migrations.AddField( + model_name='engagement', + name='reference_number', + field=models.CharField(max_length=100, null=True, verbose_name='Reference Number'), + ), + migrations.RunPython(set_reference_number), + ] diff --git a/src/etools/applications/audit/models.py b/src/etools/applications/audit/models.py index e7ec6f5f70..2b1c908ccb 100644 --- a/src/etools/applications/audit/models.py +++ b/src/etools/applications/audit/models.py @@ -186,6 +186,11 @@ class Engagement(InheritedModelMixin, TimeStampedModel, models.Model): blank=True, related_name='engagements', ) + reference_number = models.CharField( + verbose_name=_("Reference Number"), + max_length=100, + null=True, + ) objects = InheritanceManager() @@ -222,8 +227,7 @@ def displayed_status_date(self): def get_shared_ip_with_display(self): return list(map(lambda po: dict(PartnerOrganization.AGENCY_CHOICES).get(po, 'Unknown'), self.shared_ip_with)) - @property - def unique_id(self): + def get_reference_number(self): engagement_code = 'a' if self.engagement_type == self.TYPES.audit else self.engagement_type return '{}/{}/{}/{}/{}'.format( connection.tenant.country_short_code or '', @@ -233,15 +237,11 @@ def unique_id(self): self.id ) - @property - def reference_number(self): - return self.unique_id - def get_mail_context(self, **kwargs): object_url = self.get_object_url(**kwargs) return { - 'unique_id': self.unique_id, + 'unique_id': self.reference_number, 'engagement_type': self.get_engagement_type_display(), 'object_url': object_url, 'partner': force_text(self.partner), @@ -293,6 +293,12 @@ def finalize(self): def get_object_url(self, **kwargs): return build_frontend_url('ap', 'engagements', self.id, 'overview', **kwargs) + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + if not self.reference_number: + self.reference_number = self.get_reference_number() + self.save() + class RiskCategory(OrderedModel, models.Model): """Group of questions""" @@ -733,7 +739,10 @@ class Meta: ordering = ('id', ) def __str__(self): - return '{}: {}'.format(self.audit.unique_id, self.get_title_display()) + return '{}: {}'.format( + self.audit.reference_number, + self.get_title_display(), + ) class KeyInternalControl(models.Model): @@ -751,7 +760,10 @@ class Meta: ordering = ('id', ) def __str__(self): - return '{}: {}'.format(self.audit.unique_id, self.audit_observation) + return '{}: {}'.format( + self.audit.reference_number, + self.audit_observation, + ) class SpecialAudit(Engagement): @@ -823,7 +835,7 @@ class Meta: verbose_name_plural = _('Specific Procedures') def __str__(self): - return '{}: {}'.format(self.audit.unique_id, self.description) + return '{}: {}'.format(self.audit.reference_number, self.description) class SpecialAuditRecommendation(models.Model): @@ -840,7 +852,7 @@ class Meta: verbose_name_plural = _('Special Audit Recommendations') def __str__(self): - return '{}: {}'.format(self.audit.unique_id, self.description) + return '{}: {}'.format(self.audit.reference_number, self.description) class EngagementActionPointManager(models.Manager): diff --git a/src/etools/applications/audit/notifications/engagement-action_point_assigned.py b/src/etools/applications/audit/notifications/engagement-action_point_assigned.py index 1328e10c0d..be090ebcad 100644 --- a/src/etools/applications/audit/notifications/engagement-action_point_assigned.py +++ b/src/etools/applications/audit/notifications/engagement-action_point_assigned.py @@ -10,7 +10,7 @@ {{ action_point.assigned_by }} has assigned you an action point. - Engagement ID: {{ action_point.engagement.unique_id }} + Engagement ID: {{ action_point.engagement.reference_number }} Due Date: {{ action_point.due_date }} Link: {{ action_point.engagement.object_url }} @@ -25,7 +25,7 @@ {{ action_point.assigned_by }} has assigned you an action point.

- Engagement ID: {{ action_point.engagement.unique_id }}
+ Engagement ID: {{ action_point.engagement.reference_number }}
Due Date: {{ action_point.due_date }}
Link: click here

diff --git a/src/etools/applications/audit/serializers/engagement.py b/src/etools/applications/audit/serializers/engagement.py index aa243ec0f6..9f611c35a6 100644 --- a/src/etools/applications/audit/serializers/engagement.py +++ b/src/etools/applications/audit/serializers/engagement.py @@ -175,7 +175,7 @@ class EngagementExportSerializer(serializers.ModelSerializer): read_only=True ) status_date = serializers.ReadOnlyField(source='displayed_status_date') - unique_id = serializers.ReadOnlyField() + reference_number = serializers.ReadOnlyField() class Meta: model = Engagement @@ -187,7 +187,7 @@ class Meta: 'auditor_firm_name', 'status', 'status_date', - 'unique_id', + 'reference_number', ) @@ -209,7 +209,10 @@ class EngagementLightSerializer(serializers.ModelSerializer): read_only=True ) status_date = serializers.ReadOnlyField(source='displayed_status_date', label=_('Date of Status')) - unique_id = serializers.ReadOnlyField(label=_('Unique ID')) + unique_id = serializers.ReadOnlyField( + source="reference_number", + label=_('Unique ID'), + ) offices = OfficeLightSerializer(many=True) sections = SectionSerializer(many=True) diff --git a/src/etools/applications/audit/serializers/export.py b/src/etools/applications/audit/serializers/export.py index 835b368d8c..e84f54d536 100644 --- a/src/etools/applications/audit/serializers/export.py +++ b/src/etools/applications/audit/serializers/export.py @@ -98,7 +98,7 @@ class EngagementPDFSerializer(serializers.ModelSerializer): partner = PartnerPDFSerializer() engagement_type_display = serializers.ReadOnlyField(source='get_engagement_type_display') status_display = serializers.SerializerMethodField() - unique_id = serializers.ReadOnlyField() + reference_number = serializers.ReadOnlyField() authorized_officers = serializers.SerializerMethodField() active_pd = serializers.SerializerMethodField() staff_members = StaffMemberPDFSerializer(many=True) @@ -123,7 +123,7 @@ class Meta: model = Engagement fields = [ 'id', 'agreement', 'partner', 'engagement_type_display', 'engagement_type', 'status_display', 'status', - 'unique_id', 'authorized_officers', 'active_pd', 'staff_members', 'po_item', + 'reference_number', 'authorized_officers', 'active_pd', 'staff_members', 'po_item', 'date_of_field_visit', 'date_of_draft_report_to_ip', 'date_of_comments_by_ip', 'date_of_draft_report_to_unicef', 'date_of_comments_by_unicef', 'partner_contacted_at', 'action_points', 'engagement_attachments', 'report_attachments', @@ -240,7 +240,7 @@ class Meta(EngagementPDFSerializer.Meta): class EngagementBaseDetailCSVSerializer(serializers.Serializer): - unique_id = serializers.ReadOnlyField() + reference_number = serializers.ReadOnlyField() link = serializers.ReadOnlyField(source='get_object_url') auditor = serializers.ReadOnlyField(source='agreement.auditor_firm') partner = serializers.ReadOnlyField() diff --git a/src/etools/applications/audit/signals.py b/src/etools/applications/audit/signals.py index 07d35de7c3..f46980ec5d 100644 --- a/src/etools/applications/audit/signals.py +++ b/src/etools/applications/audit/signals.py @@ -26,6 +26,6 @@ def action_point_updated_receiver(instance, created, **kwargs): if created: instance.send_email(instance.assigned_to, 'audit/engagement/action_point_assigned', cc=[instance.assigned_by.email]) - else: + elif not instance.tracker.has_changed('reference_number'): if instance.tracker.has_changed('assigned_to'): instance.send_email(instance.assigned_to, 'audit/engagement/action_point_assigned') diff --git a/src/etools/applications/audit/templates/audit/engagement_pdf.html b/src/etools/applications/audit/templates/audit/engagement_pdf.html index a251d4d6d6..8132711fec 100644 --- a/src/etools/applications/audit/templates/audit/engagement_pdf.html +++ b/src/etools/applications/audit/templates/audit/engagement_pdf.html @@ -110,7 +110,7 @@ {% else %}
-
{{ engagement.unique_id }}
+
{{ engagement.reference_number }}
Engagement Overview
diff --git a/src/etools/applications/audit/views.py b/src/etools/applications/audit/views.py index edb69fbdec..e216331854 100644 --- a/src/etools/applications/audit/views.py +++ b/src/etools/applications/audit/views.py @@ -409,7 +409,7 @@ def export_pdf(self, request, *args, **kwargs): request, template, context={'engagement': pdf_serializer_class(obj).data, 'serializer': serializer}, - filename='engagement_{}.pdf'.format(obj.unique_id), + filename='engagement_{}.pdf'.format(obj.reference_number), ) @action(detail=False, methods=['get'], url_path='csv', renderer_classes=[EngagementCSVRenderer]) @@ -436,7 +436,9 @@ def export_csv(self, request, *args, **kwargs): serializer = self.csv_export_serializer(engagement) return Response(serializer.data, headers={ - 'Content-Disposition': 'attachment;filename={}.csv'.format(engagement.unique_id) + 'Content-Disposition': 'attachment;filename={}.csv'.format( + engagement.reference_number, + ) }) From 63303d6d45c636b6e47407e7ba582a67f50f9530 Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Thu, 18 Nov 2021 17:28:10 +0300 Subject: [PATCH 02/39] add max length validation for key informant source of information field --- .../field_monitoring/data_collection/offline/blueprint.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/etools/applications/field_monitoring/data_collection/offline/blueprint.py b/src/etools/applications/field_monitoring/data_collection/offline/blueprint.py index 3d65e021d8..dafbc19289 100644 --- a/src/etools/applications/field_monitoring/data_collection/offline/blueprint.py +++ b/src/etools/applications/field_monitoring/data_collection/offline/blueprint.py @@ -16,6 +16,7 @@ TextField, ) from etools.applications.offline.fields.choices import LocalPairsOptions +from etools.applications.offline.validations.text import MaxLengthTextValidation if TYPE_CHECKING: from etools.applications.field_monitoring.planning.models import MonitoringActivity @@ -43,10 +44,14 @@ def get_blueprint_for_activity_and_method(activity: 'MonitoringActivity', method blueprint.add( Group( 'information_source', - TextField('name', label=_('Source of Information'), styling=['wide']), + TextField( + 'name', label=_('Source of Information'), + styling=['wide'], validations=['information_source_max_length'], + ), styling=['card'], ) ) + blueprint.metadata.validations['information_source_max_length'] = MaxLengthTextValidation(100) for relation, level in activity.RELATIONS_MAPPING: level_block = Group(level, styling=['abstract'], required=False) From 8e12b2e00ddc502878aa7691a639ce93bd4156ce Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Thu, 18 Nov 2021 17:32:57 +0300 Subject: [PATCH 03/39] add test for new validation --- .../data_collection/tests/test_offline.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py b/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py index 42b89ffa65..f6699ecaba 100644 --- a/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py +++ b/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py @@ -101,6 +101,27 @@ def test_save_blueprint_values(self): self.assertEqual(response.status_code, status.HTTP_200_OK) + def test_save_long_information_source(self): + response = self.make_detail_request( + self.team_member, self.started_checklist, action='blueprint', method='post', + data={ + 'information_source': { + 'name': '0'*101, + }, + 'partner': { + str(self.text_question.partner.id): { + 'overall': 'overall', + 'questions': { + str(self.text_question.question_id): 'Question answer' + } + } + } + } + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn('information_source', response.data) + def test_generated_blueprint_value_accepted_for_saving(self): AttachmentFactory( content_object=self.started_checklist.overall_findings.first(), From d5363bdeaf145b4f361ec93fbf799b5c9f84665f Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Mon, 22 Nov 2021 11:15:12 +0300 Subject: [PATCH 04/39] pep8 fix --- .../field_monitoring/data_collection/tests/test_offline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py b/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py index f6699ecaba..fe8ee644f5 100644 --- a/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py +++ b/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py @@ -106,7 +106,7 @@ def test_save_long_information_source(self): self.team_member, self.started_checklist, action='blueprint', method='post', data={ 'information_source': { - 'name': '0'*101, + 'name': '0' * 101, }, 'partner': { str(self.text_question.partner.id): { From fe03a676d829a6a87fd4e47b77e02c7f346014b8 Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Tue, 23 Nov 2021 14:47:13 +0300 Subject: [PATCH 05/39] update max length error text with more relevant information --- .../field_monitoring/data_collection/tests/test_offline.py | 6 +++--- src/etools/applications/offline/fields/base.py | 2 +- src/etools/applications/offline/validations/text.py | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py b/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py index fe8ee644f5..b7f8596f55 100644 --- a/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py +++ b/src/etools/applications/field_monitoring/data_collection/tests/test_offline.py @@ -155,12 +155,12 @@ def test_save_blueprint_values_validation(self): self.started_checklist, action='blueprint', method='post', - data={'information_source': {"name": 'value' * 100}} + data={'information_source': {'name': 'value' * 100}} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertIn( - 'Ensure this field has no more than 100 characters.', + self.assertDictEqual( + {'name': ['Ensure this field has no more than 100 characters.']}, response.data['information_source'], ) diff --git a/src/etools/applications/offline/fields/base.py b/src/etools/applications/offline/fields/base.py index fa312bd632..e1a815f82d 100644 --- a/src/etools/applications/offline/fields/base.py +++ b/src/etools/applications/offline/fields/base.py @@ -110,7 +110,7 @@ def validate_single_value(self, value: Any, metadata: Metadata) -> Any: except ValidationError as ex: errors.extend(ex.detail) if errors: - raise ValidationError(set(errors)) + raise ValidationError(list(set(errors))) return value diff --git a/src/etools/applications/offline/validations/text.py b/src/etools/applications/offline/validations/text.py index 85f8832b62..23d4c10b05 100644 --- a/src/etools/applications/offline/validations/text.py +++ b/src/etools/applications/offline/validations/text.py @@ -1,6 +1,8 @@ import re -from etools.applications.offline.errors import BadValueError, ValueTypeMismatch +from django.utils.translation import ugettext_lazy as _ + +from etools.applications.offline.errors import BadValueError, ValidationError, ValueTypeMismatch from etools.applications.offline.validations.base import BaseValidation @@ -20,7 +22,7 @@ def __init__(self, max_length, **kwargs): def validate(self, value): super().validate(value) if not len(value) <= self.max_length: - raise BadValueError(value) + raise ValidationError(_('Ensure this field has no more than {0} characters.').format(self.max_length)) def to_dict(self, **kwargs): return super().to_dict(max_length=self.max_length, **kwargs) From 8d70509944f64885e9c36cc33baaf70067745fef Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Tue, 23 Nov 2021 15:52:23 +0300 Subject: [PATCH 06/39] fix non json serializable set usage in tests --- .../tests/test_contact_book_example.py | 7 +++---- .../offline/tests/test_validations.py | 19 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/etools/applications/offline/tests/test_contact_book_example.py b/src/etools/applications/offline/tests/test_contact_book_example.py index f9211aa8ff..4afa8e5ec4 100644 --- a/src/etools/applications/offline/tests/test_contact_book_example.py +++ b/src/etools/applications/offline/tests/test_contact_book_example.py @@ -1,13 +1,12 @@ import json import os -from django.test import TestCase - +from etools.applications.core.tests.cases import BaseTenantTestCase from etools.applications.offline.errors import ValidationError from etools.applications.offline.tests.contact_book import contact_book -class ContactBookExampleTestCase(TestCase): +class ContactBookExampleTestCase(BaseTenantTestCase): @classmethod def setUpTestData(cls): super().setUpTestData() @@ -58,7 +57,7 @@ def test_number_regex(self): value = {'name': 'test', 'users': [{'full_name': 'John Doe', 'phones': [{'number': '123456'}]}]} with self.assertRaises(ValidationError) as err: contact_book.validate(value) - self.assertDictEqual({'users': [{'phones': [{'number': [{'Invalid value: 123456'}]}]}]}, err.exception.detail) + self.assertDictEqual({'users': [{'phones': [{'number': ['Invalid value: 123456']}]}]}, err.exception.detail) value['users'][0]['phones'][0]['number'] = '1234567' contact_book.validate(value) diff --git a/src/etools/applications/offline/tests/test_validations.py b/src/etools/applications/offline/tests/test_validations.py index 74baf65f77..a83b7c5e3c 100644 --- a/src/etools/applications/offline/tests/test_validations.py +++ b/src/etools/applications/offline/tests/test_validations.py @@ -1,6 +1,5 @@ -from unittest import TestCase - -from etools.applications.offline.errors import BadValueError, ValueTypeMismatch +from etools.applications.core.tests.cases import BaseTenantTestCase +from etools.applications.offline.errors import BadValueError, ValidationError, ValueTypeMismatch from etools.applications.offline.validations.numbers import GreaterThanValidation, LessThanValidation from etools.applications.offline.validations.text import MaxLengthTextValidation, RegexTextValidation @@ -18,7 +17,7 @@ def test_number(self): self.get_validation().validate(1) -class TestMaxLengthTextValidation(TextBasedValidationMixin, TestCase): +class TestMaxLengthTextValidation(TextBasedValidationMixin, BaseTenantTestCase): def get_validation(self): return MaxLengthTextValidation(max_length=100) @@ -26,11 +25,11 @@ def test_valid_text(self): MaxLengthTextValidation(max_length=100).validate('1' * 100) def test_invalid_text(self): - with self.assertRaises(BadValueError): + with self.assertRaises(ValidationError): MaxLengthTextValidation(max_length=100).validate('1' * 101) -class TestRegexTextValidation(TextBasedValidationMixin, TestCase): +class TestRegexTextValidation(TextBasedValidationMixin, BaseTenantTestCase): def get_validation(self): return RegexTextValidation(regex=r'\d{6}\w') @@ -55,7 +54,7 @@ def test_text(self): self.get_validation().validate(None) -class TestLessThanValidation(NumberBasedValidation, TestCase): +class TestLessThanValidation(NumberBasedValidation, BaseTenantTestCase): def get_validation(self): return LessThanValidation(threshold=42, allow_equality=False) @@ -67,7 +66,7 @@ def test_invalid_number(self): self.get_validation().validate(42) -class TestLessThanOrEqualValidation(NumberBasedValidation, TestCase): +class TestLessThanOrEqualValidation(NumberBasedValidation, BaseTenantTestCase): def get_validation(self): return LessThanValidation(threshold=42, allow_equality=True) @@ -79,7 +78,7 @@ def test_invalid_number(self): self.get_validation().validate(43) -class TestGreaterThanValidation(NumberBasedValidation, TestCase): +class TestGreaterThanValidation(NumberBasedValidation, BaseTenantTestCase): def get_validation(self): return GreaterThanValidation(threshold=42, allow_equality=False) @@ -91,7 +90,7 @@ def test_invalid_number(self): self.get_validation().validate(42) -class TestGreaterThanOrEqualValidation(NumberBasedValidation, TestCase): +class TestGreaterThanOrEqualValidation(NumberBasedValidation, BaseTenantTestCase): def get_validation(self): return GreaterThanValidation(threshold=42, allow_equality=True) From 701ea9ae4f5aef085b8113ac6abdc5e3535e12f0 Mon Sep 17 00:00:00 2001 From: Domenico Date: Fri, 10 Dec 2021 13:11:00 -0600 Subject: [PATCH 07/39] update reqs --- Pipfile | 6 +- Pipfile.lock | 962 +++++++++++------- .../libraries/locations/tests/test_views.py | 10 +- 3 files changed, 578 insertions(+), 400 deletions(-) diff --git a/Pipfile b/Pipfile index e2bb9829a6..c01d04c943 100644 --- a/Pipfile +++ b/Pipfile @@ -69,12 +69,12 @@ Pillow = "==8.1.0" psycopg2-binary = "==2.9.1" sentry-sdk = "*" requests = "==2.26" -social-auth-app-django = "==4.0" +social-auth-app-django = "==5.0" social-auth-core = {extras = ["azuread"],version = "==4.1"} tenant-schemas-celery = "==1.0.1" -unicef-attachments = "==0.9.0" +unicef-attachments = "==0.10.1" unicef-djangolib = "==0.5.4" -unicef-locations = "==3.0" +unicef-locations = "==3.1" unicef-notification = "==1.1" unicef-restlib = "==0.7" unicef-snapshot = "==1.1" diff --git a/Pipfile.lock b/Pipfile.lock index bd41d61d8a..3add5f1ee4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0cb5cab341c162cf5aa3b1d165d31a3f6f0bba9093dc00186a48261d30076db1" + "sha256": "bfdcf8edbf2ccb62e4fbcd8be1f972d8ede32b7dc4fedd388acaacb859782004" }, "pipfile-spec": 6, "requires": { @@ -94,68 +94,73 @@ }, "certifi": { "hashes": [ - "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", - "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" + "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", + "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" ], - "version": "==2021.5.30" + "version": "==2021.10.8" }, "cffi": { "hashes": [ - "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d", - "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771", - "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872", - "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c", - "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc", - "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762", - "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202", - "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5", - "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548", - "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a", - "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f", - "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20", - "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218", - "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c", - "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e", - "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56", - "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224", - "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a", - "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2", - "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a", - "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819", - "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346", - "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b", - "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e", - "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534", - "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb", - "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0", - "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156", - "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd", - "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87", - "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc", - "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195", - "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33", - "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f", - "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d", - "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd", - "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728", - "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7", - "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca", - "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99", - "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf", - "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e", - "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c", - "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5", - "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69" - ], - "version": "==1.14.6" + "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", + "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", + "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", + "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", + "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", + "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", + "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", + "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", + "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", + "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", + "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", + "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", + "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", + "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", + "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", + "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", + "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", + "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", + "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", + "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", + "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", + "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", + "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", + "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", + "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", + "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", + "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", + "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", + "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", + "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", + "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", + "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", + "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", + "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", + "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", + "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", + "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", + "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", + "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", + "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", + "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", + "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", + "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", + "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", + "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", + "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", + "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", + "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", + "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", + "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" + ], + "version": "==1.15.0" }, "charset-normalizer": { "hashes": [ - "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6", - "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f" + "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721", + "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c" ], "markers": "python_version >= '3'", - "version": "==2.0.6" + "version": "==2.0.9" }, "click": { "hashes": [ @@ -591,18 +596,18 @@ }, "humanize": { "hashes": [ - "sha256:06c79af7873473c47477840010ccb9b11b0d431f37f4a81b71edd653211936be", - "sha256:4160cdc63fcd0daac27d2e1e218a31bb396fc3fe5712d153675d89432a03778f" + "sha256:12f113f2e369dac7f35d3823f49262934f4a22a53a6d3d4c86b736f50db88c7b", + "sha256:a6f7cc1597db69a4e571ad5e19b4da07ee871da5a9de2b233dbfab02d98e9754" ], - "version": "==3.11.0" + "version": "==3.13.1" }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3'", - "version": "==3.2" + "version": "==3.3" }, "itypes": { "hashes": [ @@ -620,10 +625,10 @@ }, "jinja2": { "hashes": [ - "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4", - "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4" + "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", + "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7" ], - "version": "==3.0.1" + "version": "==3.0.3" }, "jsonfield": { "hashes": [ @@ -634,63 +639,75 @@ }, "kombu": { "hashes": [ - "sha256:01481d99f4606f6939cdc9b637264ed353ee9e3e4f62cfb582324142c41a572d", - "sha256:e2dedd8a86c9077c350555153825a31e456a0dc20c15d5751f00137ec9c75f0a" + "sha256:0f5d0763fb916808f617b886697b2be28e6bc35026f08e679697fc814b48a608", + "sha256:d36f0cde6a18d9eb7b6b3aa62a59bfdff7f5724689850e447eca5be8efc9d501" ], - "version": "==5.1.0" + "version": "==5.2.2" }, "lxml": { "hashes": [ - "sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d", - "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3", - "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2", - "sha256:1b38116b6e628118dea5b2186ee6820ab138dbb1e24a13e478490c7db2f326ae", - "sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f", - "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927", - "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3", - "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7", - "sha256:3082c518be8e97324390614dacd041bb1358c882d77108ca1957ba47738d9d59", - "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f", - "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade", - "sha256:36108c73739985979bf302006527cf8a20515ce444ba916281d1c43938b8bb96", - "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468", - "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b", - "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4", - "sha256:4c61b3a0db43a1607d6264166b230438f85bfed02e8cff20c22e564d0faff354", - "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83", - "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04", - "sha256:5c8c163396cc0df3fd151b927e74f6e4acd67160d6c33304e805b84293351d16", - "sha256:64812391546a18896adaa86c77c59a4998f33c24788cadc35789e55b727a37f4", - "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791", - "sha256:6f12e1427285008fd32a6025e38e977d44d6382cf28e7201ed10d6c1698d2a9a", - "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51", - "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1", - "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a", - "sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f", - "sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee", - "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec", - "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969", - "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28", - "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a", - "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa", - "sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106", - "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d", - "sha256:c1a40c06fd5ba37ad39caa0b3144eb3772e813b5fb5b084198a985431c2f1e8d", - "sha256:c47ff7e0a36d4efac9fd692cfa33fbd0636674c102e9e8d9b26e1b93a94e7617", - "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4", - "sha256:cdaf11d2bd275bf391b5308f86731e5194a21af45fbaaaf1d9e8147b9160ea92", - "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0", - "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4", - "sha256:d916d31fd85b2f78c76400d625076d9124de3e4bda8b016d25a050cc7d603f24", - "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2", - "sha256:e1cbd3f19a61e27e011e02f9600837b921ac661f0c40560eefb366e4e4fb275e", - "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0", - "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654", - "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2", - "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23", - "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586" - ], - "version": "==4.6.3" + "sha256:08eb9200d88b376a8ed5e50f1dc1d1a45b49305169674002a3b5929943390591", + "sha256:0b12c95542f04d10cba46b3ff28ea52ea56995b78cf918f0b11b05e75812bb79", + "sha256:0c15e1cd55055956e77b0732270f1c6005850696bc3ef3e03d01e78af84eaa42", + "sha256:15d0381feb56f08f78c5cc4fc385ddfe0bde1456e37f54a9322833371aec4060", + "sha256:197b7cb7a753cf553a45115739afd8458464a28913da00f5c525063f94cd3f48", + "sha256:20d7c8d90d449c6a353b15ee0459abae8395dbe59ad01e406ccbf30cd81c6f98", + "sha256:240db6f3228d26e3c6f4fad914b9ddaaf8707254e8b3efd564dc680c8ec3c264", + "sha256:2901625f4a878a055d275beedc20ba9cb359cefc4386a967222fee29eb236038", + "sha256:2b06a91cf7b8acea7793006e4ae50646cef0fe35ce5acd4f5cb1c77eb228e4a1", + "sha256:2eb90f6ec3c236ef2f1bb38aee7c0d23e77d423d395af6326e7cca637519a4cb", + "sha256:351482da8dd028834028537f08724b1de22d40dcf3bb723b469446564f409074", + "sha256:35752ee40f7bbf6adc9ff4e1f4b84794a3593736dcce80db32e3c2aa85e294ac", + "sha256:38b9de0de3aa689fe9fb9877ae1be1e83b8cf9621f7e62049d0436b9ecf4ad64", + "sha256:433df8c7dde0f9e41cbf4f36b0829d50a378116ef5e962ba3881f2f5f025c7be", + "sha256:4341d135f5660db10184963d9c3418c3e28d7f868aaf8b11a323ebf85813f7f4", + "sha256:45fdb2899c755138722797161547a40b3e2a06feda620cc41195ee7e97806d81", + "sha256:4717123f7c11c81e0da69989e5a64079c3f402b0efeb4c6241db6c369d657bd8", + "sha256:47e955112ce64241fdb357acf0216081f9f3255b3ac9c502ca4b3323ec1ca558", + "sha256:48eaac2991b3036175b42ee8d3c23f4cca13f2be8426bf29401a690ab58c88f4", + "sha256:4aa349c5567651f34d4eaae7de6ed5b523f6d70a288f9c6fbac22d13a0784e04", + "sha256:4ba74afe5ee5cb5e28d83b513a6e8f0875fda1dc1a9aea42cc0065f029160d2a", + "sha256:4ec9a80dd5704ecfde54319b6964368daf02848c8954d3bacb9b64d1c7659159", + "sha256:50790313df028aa05cf22be9a8da033b86c42fa32523e4fd944827b482b17bf0", + "sha256:51a0e5d243687596f46e24e464121d4b232ad772e2d1785b2a2c0eb413c285d4", + "sha256:523f195948a1ba4f9f5b7294d83c6cd876547dc741820750a7e5e893a24bbe38", + "sha256:543b239b191bb3b6d9bef5f09f1fb2be5b7eb09ab4d386aa655e4d53fbe9ff47", + "sha256:5ff5bb2a198ea67403bb6818705e9a4f90e0313f2215428ec51001ce56d939fb", + "sha256:601f0ab75538b280aaf1e720eb9d68d4fa104ac274e1e9e6971df488f4dcdb0f", + "sha256:6020c70ff695106bf80651953a23e37718ef1fee9abd060dcad8e32ab2dc13f3", + "sha256:619c6d2b552bba00491e96c0518aad94002651c108a0f7364ff2d7798812c00e", + "sha256:6298f5b42a26581206ef63fffa97c754245d329414108707c525512a5197f2ba", + "sha256:662523cd2a0246740225c7e32531f2e766544122e58bee70e700a024cfc0cf81", + "sha256:6764998345552b1dfc9326a932d2bad6367c6b37a176bb73ada6b9486bf602f7", + "sha256:6d422b3c729737d8a39279a25fa156c983a56458f8b2f97661ee6fb22b80b1d6", + "sha256:72e730d33fe2e302fd07285f14624fca5e5e2fb2bb4fb2c3941e318c41c443d1", + "sha256:75d3c5bbc0ddbad03bb68b9be638599f67e4b98ed3dcd0fec9f6f39e41ee96cb", + "sha256:7ae7089d81fc502df4b217ad77f03c54039fe90dac0acbe70448d7e53bfbc57e", + "sha256:80d10d53d3184837445ff8562021bdd37f57c4cadacbf9d8726cc16220a00d54", + "sha256:877666418598f6cb289546c77ff87590cfd212f903b522b0afa0b9fb73b3ccfb", + "sha256:9b87727561c1150c0cc91c5d9d389448b37a7d15f0ba939ed3d1acb2f11bf6c5", + "sha256:9c91a73971a922c13070fd8fa5a114c858251791ba2122a941e6aa781c713e44", + "sha256:9db24803fa71e3305fe4a7812782b708da21a0b774b130dd1860cf40a6d7a3ee", + "sha256:a75c1ad05eedb1a3ff2a34a52a4f0836cfaa892e12796ba39a7732c82701eff4", + "sha256:a77a3470ba37e11872c75ca95baf9b3312133a3d5a5dc720803b23098c653976", + "sha256:ab6db93a2b6b66cbf62b4e4a7135f476e708e8c5c990d186584142c77d7f975a", + "sha256:afd60230ad9d8bcba005945ec3a343722f09e0b7f8ae804246e5d2cfc6bd71a6", + "sha256:b0ca0ada9d3bc18bd6f611bd001a28abdd49ab9698bd6d717f7f5394c8e94628", + "sha256:b567178a74a2261345890eac66fbf394692a6e002709d329f28a673ca6042473", + "sha256:b667c51682fe9b9788c69465956baa8b6999531876ccedcafc895c74ad716cd8", + "sha256:bbf2dc330bd44bfc0254ab37677ec60f7c7ecea55ad8ba1b8b2ea7bf20c265f5", + "sha256:bdc224f216ead849e902151112efef6e96c41ee1322e15d4e5f7c8a826929aee", + "sha256:cf201bf5594d1aab139fe53e3fca457e4f8204a5bbd65d48ab3b82a16f517868", + "sha256:d43bd68714049c84e297c005456a15ecdec818f7b5aa5868c8b0a865cfb78a44", + "sha256:daf9bd1fee31f1c7a5928b3e1059e09a8d683ea58fb3ffc773b6c88cb8d1399c", + "sha256:e678a643177c0e5ec947b645fa7bc84260dfb9b6bf8fb1fdd83008dfc2ca5928", + "sha256:e91d24623e747eeb2d8121f4a94c6a7ad27dc48e747e2dc95bfe88632bd028a2", + "sha256:e95da348d57eb448d226a44b868ff2ca5786fbcbe417ac99ff62d0a7d724b9c7", + "sha256:ee9e4b07b0eba4b6a521509e9e1877476729c1243246b6959de697ebea739643", + "sha256:f5dd358536b8a964bf6bd48de038754c1609e72e5f17f5d21efe2dda17594dbf", + "sha256:ffd65cfa33fed01735c82aca640fde4cc63f0414775cba11e06f84fae2085a6e" + ], + "version": "==4.6.4" }, "markuppy": { "hashes": [ @@ -703,6 +720,7 @@ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", + "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194", "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", @@ -710,6 +728,7 @@ "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", + "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a", "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", @@ -717,27 +736,36 @@ "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", + "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047", "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", + "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b", "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", + "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1", "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", + "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee", + "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f", "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", + "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86", + "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6", "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", + "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e", "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", + "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f", "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d", @@ -745,10 +773,14 @@ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066", "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c", "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1", + "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a", + "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207", "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f", "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53", + "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd", "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134", "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85", + "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9", "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5", "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94", "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509", @@ -759,22 +791,24 @@ }, "newrelic": { "hashes": [ - "sha256:05cbb835029c95befb5bed213a81b38c0acf6eb740fd01a7651d75519078f896", - "sha256:36d491ace729402e7f9b7d6e9db78a416ed27525873dea224eae11797429a03f", - "sha256:60aece67d509aee9ed627a9b39c0d3d8c02879f4b33f90b5a1964bf77473e8cd", - "sha256:6da1729a814b1781a3f3e20f26bce9cef2ffac166a0aed3f33afad4a73593623", - "sha256:6fd331f84dabebd1ef24d8756883b90e43fdbb7d89ce417ca5a35dcece0e5bbc", - "sha256:715261cd18b2e58574f7997cd64eec970de2e34375dd14ade3a6f4473a6fc536", - "sha256:79941674e6d57b0b6d4f3960cd92ceedfd2abf75834dd0687f0dea0b373c3da5", - "sha256:7d14ade92c31f68ce4f038241f5ef85c34b45e0c9ae03b06e527b59a938d54f8", - "sha256:87dcb0ad8988d800e1ec020ddadaba4a35603ca620c5f7e9b132cc2eeab48fc5", - "sha256:99e31c6c39a2add985affc186a67722db5da74d01c794123dcdf64a08fcd19be", - "sha256:eb5f5b1ba142ab0518c19f00ee00e9935949d267430c36cb29432bd879d39411", - "sha256:f2494c38bd0e62220c2af697b1a747d423eca6c177607d52c8678ad5513ff95d", - "sha256:fe4189ed9157e97363bc4535e18b9b7d20ab3e9ec02accf5b9232e3fe77531aa" - ], - "index": "pypi", - "version": "==7.0.0.166" + "sha256:1cb3ed22ed3c119e557f3a097b2bbcfb6c0aa5aa9842b1fa09d2a8145f4d931a", + "sha256:25fa6091bb6881d9e2918655fe3f1390c080f6f74f9e6607555fb29230836d91", + "sha256:48cac4a9815907df85e9ce287ec9c6172fe4faa57f1750663d8846104d51af78", + "sha256:53835848acb863acc1bc415097156661c7f3c5d483bbfbf9cf19312182fcb797", + "sha256:60c50b17a25128b1400a868304278128ce3d6379acb7b12893efcb5725922e45", + "sha256:8a7f8e46bd02f39d2abb67c39b19a860e8b6ce2263a37ee1fa5744cbfef61f85", + "sha256:9efdb7432457f4cdab03aa417bd1e80974786039c7fddff9fb0c71325e35eea7", + "sha256:a5f3f9e87358bce7ab21789c52d4b16a586b21c6ac70deec2c34c5c87e96fc44", + "sha256:b37e1fa55489a63dd3b76742fc357d02b18ced49ff4efb0da42865beae651956", + "sha256:b85ccfdfef4ca3bb3a25afbbe5281cf2bcdac41e63d5d118e6a1fc405add09ec", + "sha256:c59f76676529e8fb1627333622b9debd3cb825c4f1ee325d1d0249d35bdead0d", + "sha256:e3d59a7d08c32bd386c804057618a2b68b829b2e444c42dddfc0da3eff0eeeb3", + "sha256:ec3d2012c035e846e8c6ca0629decceb3f65eca88e787ab58fc0c56dbf933936", + "sha256:fa5c6a4e8c3feadfc8c246631c631735c91b8f4f0a380add1b629415005b12c0", + "sha256:fee14166041cfdf9743083b4398056d1cd8c727d4df2e3c2090e627ee33e3ddf" + ], + "index": "pypi", + "version": "==7.2.4.171" }, "oauthlib": { "hashes": [ @@ -850,10 +884,10 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c", - "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c" + "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6", + "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506" ], - "version": "==3.0.20" + "version": "==3.0.24" }, "psycopg2-binary": { "hashes": [ @@ -864,13 +898,18 @@ "sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90", "sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a", "sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e", + "sha256:1f6ca4a9068f5c5c57e744b4baa79f40e83e3746875cac3c45467b16326bab45", "sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d", + "sha256:24b0b6688b9f31a911f2361fe818492650795c9e5d3a1bc647acbd7440142a4f", "sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed", "sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a", "sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140", "sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32", + "sha256:542875f62bc56e91c6eac05a0deadeae20e1730be4c6334d8f04c944fcd99759", "sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31", + "sha256:661509f51531ec125e52357a489ea3806640d0ca37d9dada461ffc69ee1e7b6e", "sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a", + "sha256:736b8797b58febabb85494142c627bd182b50d2a7ec65322983e71065ad3034c", "sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917", "sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf", "sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7", @@ -882,7 +921,9 @@ "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76", "sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4", "sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f", + "sha256:d92272c7c16e105788efe2cfa5d680f07e34e0c29b03c1908f8636f55d5f915a", "sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34", + "sha256:ebccf1123e7ef66efc615a68295bf6fdba875a75d5bba10a05073202598085fc", "sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce", "sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a", "sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e" @@ -892,17 +933,17 @@ }, "pycparser": { "hashes": [ - "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", - "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" ], - "version": "==2.20" + "version": "==2.21" }, "pyjwt": { "hashes": [ - "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1", - "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130" + "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41", + "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f" ], - "version": "==2.1.0" + "version": "==2.3.0" }, "pypdf2": { "hashes": [ @@ -925,9 +966,9 @@ }, "python-crontab": { "hashes": [ - "sha256:4bbe7e720753a132ca4ca9d4094915f40e9d9dc8a807a4564007651018ce8c31" + "sha256:1e35ed7a3cdc3100545b43e196d34754e6551e7f95e4caebbe0e1c0ca41c2f1b" ], - "version": "==2.5.1" + "version": "==2.6.0" }, "python-dateutil": { "hashes": [ @@ -1007,31 +1048,42 @@ }, "reportlab": { "hashes": [ - "sha256:00e9ffb955972a8f6a3a0d61a12231fcaf5e23ee238c98421d65fecc29bd88a1", - "sha256:115177b3fc51209b5f50371735311c9a6cd9d260ffedbdce5fbc965645b7567c", - "sha256:17130f034dae50aaf22fce2292e0077a0c2093ba4363211bcafb54418fb8dc09", - "sha256:200bdfc327d5b06cb400ae86c972b579efe03a1fd8a2e8cb7a5d9aaa744e5adb", - "sha256:496b28ef414d9a7734e07221c4386bb00f416a3aa276b9f349ed9a328c73ec23", - "sha256:4bc378039f70141176f3d511d84bc1a172820d4d2edee4f9fcff52cde753dc08", - "sha256:4f357b4c39b0fa0071de47e8be7af44e07f375d2e59e395daccb7fd13b275668", - "sha256:57b39303e6dbe3de91e60a14269543ac058ac98a0ea6cf900f5403d9c226022f", - "sha256:6472478e597ef4a8f5c621d811d08b7ef09fc5af5bc85c2cf4a4505a7164f8b8", - "sha256:68f9324000cfc5570b5a59a92306691b5d655078a399f20bc72c2581fe903261", - "sha256:69870e2bbf39b60ebe9a31b31324e249bf314bdc2798e46efc58c67db74b56cb", - "sha256:6adb17ba89829d5e77fd81baac396f1af99241d7dfc121a065217334131662e7", - "sha256:7c360aee2bdaa05c24cadddc2f10924961dc7cad125d8876b4d307c879b3b4e8", - "sha256:7c4c8e87ef29714ccc7fa9764efe30d849cd38f8a9a1742ab7aedf8b5e23494d", - "sha256:8a07672e86bf288ea3e55959d2e06d6c01320318662241f9b7a71c583e15e5b5", - "sha256:9f583295f7dd523bf6e5619720677279dc7b9db22671573888f0591fc46b90b2", - "sha256:b668433f32ac955a94633e58ed7800c06c00f9c46d3b99e2189b3d88dc3184c8", - "sha256:b7a92564198c5a5ff4efdb83ace215c73343afb80d9379183bc736fea76edd6d", - "sha256:bd52e1715c70a96a116a61c8477e586b3a46047c85581195bc74162b19b46286", - "sha256:c7ddc9a6234267bbb52059b017ca22f59ffd7d41d545524cb85f68086a2cbb43", - "sha256:c8586d72932b8e3bd50a5230d6f1cfbb85c2605bad34253c6d6fe757211b2bf7", - "sha256:ce3d8e782e3776f19d3accc706aab85ff06caedb70a52016532bebacf5537567", - "sha256:f3fd26f63c4a9033115707a8718154538a1cebfd6ec992f214e6423524450e3e" - ], - "version": "==3.6.1" + "sha256:0c2f479df4eb447ea0757bf60b1ac0d7ddb9980335f4f94975ee6d95bda5b8f8", + "sha256:1055380b2dc73d5143a62451f81b2a739f605dae0e107a764efc0618293837c1", + "sha256:169d7017687c60ddf7690cb349e24ae10d51480d93babc6f81d851aea8a01a25", + "sha256:27ce3e8869c3f22d9d7a8092858649601e76b86e2f3032df39566343b908d929", + "sha256:2efdb2999e1b19a16d5535aa70b5ec5f3ad003e1d366da566f23231ff81400aa", + "sha256:2fa30756c2d5d5e11321114636b0cbeffdf59ffdbcf705b902057ad3801d0d37", + "sha256:3b85b7172b9b4ab0ae74fe0e99d9186ff04104d9158c980391f4e0a54b67f3a8", + "sha256:3d5d9997b91ec7f2d1a2b9928ab20503cf70e8c056b445d0bc7ae29946c13623", + "sha256:50e62429a3487722b4d7621453efc4cbeed80f3b608cad98ef8f06d191a8d0a9", + "sha256:5785aab3b57fe4794147da8908d411c3abf900ac2bc5b0c39782205a1d8c5b51", + "sha256:5d1280c9df17a5d36213b88d66f45a9475005ab39d79b6e9e98893a02a5a033d", + "sha256:68de7f3d3511ea45b9af6e9e4a6b6d89a86d1fe59f41583fb55e6c810ebf23d9", + "sha256:720335d2462ed8ad5ad6ea5da509a9289fab7a78b0cdcdfd56fef5398435119d", + "sha256:7cb6a4ea5cfc08669c0ba66e900cf5c598c33fdb0e3e4ebadf892ff703d594f6", + "sha256:7e51f0195e602c207edcf3a768a6005a10b3db786539b74eb99afe6c9fd5656a", + "sha256:ae3959094b48bdae729e838d84156d31691f0bd17c640b8b10ff0fdbbc11c031", + "sha256:af350308e8b8720ca6db7763b56e96b37976576c1f8b0069764074dc41a19254", + "sha256:b75a4f634e8ba89cc22ff58b9bdfd01a239b2e2fc85d086d1a2d70d08167c443", + "sha256:bb8c380bceb3623f39a96b6bc8cf8db75857fea3f67900391763b5caee23ffa3", + "sha256:be4f05230eb17b9c9c61a180ab0c89c30112da2823c77807a2a5ddba19365865", + "sha256:c166a6c168232948e9b100dcab1b88a4b21efe0aa14c5c18bafd28fffffb4576", + "sha256:c29e7cde992c56687c6f68053dea4aa3beb0d406df28738e95950d88deb38109", + "sha256:c4e0abfa0daf0c48a6bffc46c51b2e5f6272a1d57593c51e7bc855272f763130", + "sha256:c79f89c277f49dfd2829b9a046b20c12cd46fe69f474e4dca349e731a2397021", + "sha256:d35cc6ae73a25b2e75b23e60d3dca0e5153dff97d9e22b28ac82712c79656fd9", + "sha256:d57b5374a44aab9f3898c57ed3c2e6ba159878a2a37f36ddd154adf6f4b3a5c0", + "sha256:d5b56d9912f148cca4fdc0d6c805a56931bb1a4e59e899db92a3531e78f2a9de", + "sha256:d7145d010d561c502e51795adb2e4f7534f28f12e32db0b0694081c6173c8b27", + "sha256:d851fecf4bb6484d4038a402430f30294911aa116686624d1e79b9e3cdb1ed2c", + "sha256:d94a20b7f2aad166ffe74a77bff02d82a82c514dba6d3e431fdb14675db5c383", + "sha256:dcbf4bcf0917cb50964a9c47198e802791eae2581e7788f43da8f50ed5744d8a", + "sha256:e8b214321e2e16209a68a4cdbe3391379845cd0da434362cf3c6d2d1053146fe", + "sha256:f0cc8308678a8136481572463e5ac92a145d2fb487aa22c842347af8a063d50a", + "sha256:f2c0977a39bea423f6a0b53faaabef3b2f8602b1d3e09c57f6952d60ad363119" + ], + "version": "==3.6.3" }, "requests": { "hashes": [ @@ -1050,62 +1102,77 @@ }, "sentry-sdk": { "hashes": [ - "sha256:b9844751e40710e84a457c5bc29b21c383ccb2b63d76eeaad72f7f1c808c8828", - "sha256:c091cc7115ff25fe3a0e410dbecd7a996f81a3f6137d2272daef32d6c3cfa6dc" + "sha256:0db297ab32e095705c20f742c3a5dac62fe15c4318681884053d0898e5abb2f6", + "sha256:789a11a87ca02491896e121efdd64e8fd93327b69e8f2f7d42f03e2569648e88" ], "index": "pypi", - "version": "==1.4.3" + "version": "==1.5.0" }, "simplejson": { "hashes": [ - "sha256:065230b9659ac38c8021fa512802562d122afb0cf8d4b89e257014dcddb5730a", - "sha256:07707ba69324eaf58f0c6f59d289acc3e0ed9ec528dae5b0d4219c0d6da27dc5", - "sha256:10defa88dd10a0a4763f16c1b5504e96ae6dc68953cfe5fc572b4a8fcaf9409b", - "sha256:140eb58809f24d843736edb8080b220417e22c82ac07a3dfa473f57e78216b5f", - "sha256:188f2c78a8ac1eb7a70a4b2b7b9ad11f52181044957bf981fb3e399c719e30ee", - "sha256:1c2688365743b0f190392e674af5e313ebe9d621813d15f9332e874b7c1f2d04", - "sha256:24e413bd845bd17d4d72063d64e053898543fb7abc81afeae13e5c43cef9c171", - "sha256:2b59acd09b02da97728d0bae8ff48876d7efcbbb08e569c55e2d0c2e018324f5", - "sha256:2df15814529a4625ea6f7b354a083609b3944c269b954ece0d0e7455872e1b2a", - "sha256:352c11582aa1e49a2f0f7f7d8fd5ec5311da890d1354287e83c63ab6af857cf5", - "sha256:36b08b886027eac67e7a0e822e3a5bf419429efad7612e69501669d6252a21f2", - "sha256:376023f51edaf7290332dacfb055bc00ce864cb013c0338d0dea48731f37e42f", - "sha256:3ba82f8b421886f4a2311c43fb98faaf36c581976192349fef2a89ed0fcdbdef", - "sha256:3d72aa9e73134dacd049a2d6f9bd219f7be9c004d03d52395831611d66cedb71", - "sha256:40ece8fa730d1a947bff792bcc7824bd02d3ce6105432798e9a04a360c8c07b0", - "sha256:417b7e119d66085dc45bdd563dcb2c575ee10a3b1c492dd3502a029448d4be1c", - "sha256:42b7c7264229860fe879be961877f7466d9f7173bd6427b3ba98144a031d49fb", - "sha256:457d9cfe7ece1571770381edccdad7fc255b12cd7b5b813219441146d4f47595", - "sha256:4a6943816e10028eeed512ea03be52b54ea83108b408d1049b999f58a760089b", - "sha256:5b94df70bd34a3b946c0eb272022fb0f8a9eb27cad76e7f313fedbee2ebe4317", - "sha256:5f5051a13e7d53430a990604b532c9124253c5f348857e2d5106d45fc8533860", - "sha256:5f7f53b1edd4b23fb112b89208377480c0bcee45d43a03ffacf30f3290e0ed85", - "sha256:5fe8c6dcb9e6f7066bdc07d3c410a2fca78c0d0b4e0e72510ffd20a60a20eb8e", - "sha256:71a54815ec0212b0cba23adc1b2a731bdd2df7b9e4432718b2ed20e8aaf7f01a", - "sha256:7332f7b06d42153255f7bfeb10266141c08d48cc1a022a35473c95238ff2aebc", - "sha256:78c6f0ed72b440ebe1892d273c1e5f91e55e6861bea611d3b904e673152a7a4c", - "sha256:7c9b30a2524ae6983b708f12741a31fbc2fb8d6fecd0b6c8584a62fd59f59e09", - "sha256:86fcffc06f1125cb443e2bed812805739d64ceb78597ac3c1b2d439471a09717", - "sha256:87572213965fd8a4fb7a97f837221e01d8fddcfb558363c671b8aa93477fb6a2", - "sha256:8e595de17178dd3bbeb2c5b8ea97536341c63b7278639cb8ee2681a84c0ef037", - "sha256:917f01db71d5e720b731effa3ff4a2c702a1b6dacad9bcdc580d86a018dfc3ca", - "sha256:91cfb43fb91ff6d1e4258be04eee84b51a4ef40a28d899679b9ea2556322fb50", - "sha256:aa86cfdeb118795875855589934013e32895715ec2d9e8eb7a59be3e7e07a7e1", - "sha256:ade09aa3c284d11f39640aebdcbb748e1996f0c60504f8c4a0c5a9fec821e67a", - "sha256:b2a5688606dffbe95e1347a05b77eb90489fe337edde888e23bbb7fd81b0d93b", - "sha256:b92fbc2bc549c5045c8233d954f3260ccf99e0f3ec9edfd2372b74b350917752", - "sha256:c2d5334d935af711f6d6dfeec2d34e071cdf73ec0df8e8bd35ac435b26d8da97", - "sha256:cb0afc3bad49eb89a579103616574a54b523856d20fc539a4f7a513a0a8ba4b2", - "sha256:ce66f730031b9b3683b2fc6ad4160a18db86557c004c3d490a29bf8d450d7ab9", - "sha256:e29b9cea4216ec130df85d8c36efb9985fda1c9039e4706fb30e0fb6a67602ff", - "sha256:e2cc4b68e59319e3de778325e34fbff487bfdb2225530e89995402989898d681", - "sha256:e90d2e219c3dce1500dda95f5b893c293c4d53c4e330c968afbd4e7a90ff4a5b", - "sha256:f13c48cc4363829bdfecc0c181b6ddf28008931de54908a492dc8ccd0066cd60", - "sha256:f550730d18edec4ff9d4252784b62adfe885d4542946b6d5a54c8a6521b56afd", - "sha256:fa843ee0d34c7193f5a816e79df8142faff851549cab31e84b526f04878ac778", - "sha256:fe1c33f78d2060719d52ea9459d97d7ae3a5b707ec02548575c4fbed1d1d345b" - ], - "version": "==3.17.5" + "sha256:04e31fa6ac8e326480703fb6ded1488bfa6f1d3f760d32e29dbf66d0838982ce", + "sha256:068670af975247acbb9fc3d5393293368cda17026db467bf7a51548ee8f17ee1", + "sha256:07ecaafc1b1501f275bf5acdee34a4ad33c7c24ede287183ea77a02dc071e0c0", + "sha256:0b4126cac7d69ac06ff22efd3e0b3328a4a70624fcd6bca4fc1b4e6d9e2e12bf", + "sha256:0de783e9c2b87bdd75b57efa2b6260c24b94605b5c9843517577d40ee0c3cc8a", + "sha256:12133863178a8080a3dccbf5cb2edfab0001bc41e5d6d2446af2a1131105adfe", + "sha256:1c9b1ed7ed282b36571638297525f8ef80f34b3e2d600a56f962c6044f24200d", + "sha256:23fe704da910ff45e72543cbba152821685a889cf00fc58d5c8ee96a9bad5f94", + "sha256:28221620f4dcabdeac310846629b976e599a13f59abb21616356a85231ebd6ad", + "sha256:35a49ebef25f1ebdef54262e54ae80904d8692367a9f208cdfbc38dbf649e00a", + "sha256:37bc0cf0e5599f36072077e56e248f3336917ded1d33d2688624d8ed3cefd7d2", + "sha256:3fe87570168b2ae018391e2b43fbf66e8593a86feccb4b0500d134c998983ccc", + "sha256:3ff5b3464e1ce86a8de8c88e61d4836927d5595c2162cab22e96ff551b916e81", + "sha256:401d40969cee3df7bda211e57b903a534561b77a7ade0dd622a8d1a31eaa8ba7", + "sha256:4b6bd8144f15a491c662f06814bd8eaa54b17f26095bb775411f39bacaf66837", + "sha256:4c09868ddb86bf79b1feb4e3e7e4a35cd6e61ddb3452b54e20cf296313622566", + "sha256:4d1c135af0c72cb28dd259cf7ba218338f4dc027061262e46fe058b4e6a4c6a3", + "sha256:4ff4ac6ff3aa8f814ac0f50bf218a2e1a434a17aafad4f0400a57a8cc62ef17f", + "sha256:521877c7bd060470806eb6335926e27453d740ac1958eaf0d8c00911bc5e1802", + "sha256:522fad7be85de57430d6d287c4b635813932946ebf41b913fe7e880d154ade2e", + "sha256:5540fba2d437edaf4aa4fbb80f43f42a8334206ad1ad3b27aef577fd989f20d9", + "sha256:5d6b4af7ad7e4ac515bc6e602e7b79e2204e25dbd10ab3aa2beef3c5a9cad2c7", + "sha256:5decdc78849617917c206b01e9fc1d694fd58caa961be816cb37d3150d613d9a", + "sha256:632ecbbd2228575e6860c9e49ea3cc5423764d5aa70b92acc4e74096fb434044", + "sha256:65b998193bd7b0c7ecdfffbc825d808eac66279313cb67d8892bb259c9d91494", + "sha256:67093a526e42981fdd954868062e56c9b67fdd7e712616cc3265ad0c210ecb51", + "sha256:681eb4d37c9a9a6eb9b3245a5e89d7f7b2b9895590bb08a20aa598c1eb0a1d9d", + "sha256:69bd56b1d257a91e763256d63606937ae4eb890b18a789b66951c00062afec33", + "sha256:724c1fe135aa437d5126138d977004d165a3b5e2ee98fc4eb3e7c0ef645e7e27", + "sha256:7255a37ff50593c9b2f1afa8fafd6ef5763213c1ed5a9e2c6f5b9cc925ab979f", + "sha256:743cd768affaa508a21499f4858c5b824ffa2e1394ed94eb85caf47ac0732198", + "sha256:80d3bc9944be1d73e5b1726c3bbfd2628d3d7fe2880711b1eb90b617b9b8ac70", + "sha256:82ff356ff91be0ab2293fc6d8d262451eb6ac4fd999244c4b5f863e049ba219c", + "sha256:8e8607d8f6b4f9d46fee11447e334d6ab50e993dd4dbfb22f674616ce20907ab", + "sha256:97202f939c3ff341fc3fa84d15db86156b1edc669424ba20b0a1fcd4a796a045", + "sha256:9b01e7b00654115965a206e3015f0166674ec1e575198a62a977355597c0bef5", + "sha256:9fa621b3c0c05d965882c920347b6593751b7ab20d8fa81e426f1735ca1a9fc7", + "sha256:a1aa6e4cae8e3b8d5321be4f51c5ce77188faf7baa9fe1e78611f93a8eed2882", + "sha256:a2d30d6c1652140181dc6861f564449ad71a45e4f165a6868c27d36745b65d40", + "sha256:a649d0f66029c7eb67042b15374bd93a26aae202591d9afd71e111dd0006b198", + "sha256:a7854326920d41c3b5d468154318fe6ba4390cb2410480976787c640707e0180", + "sha256:a89acae02b2975b1f8e4974cb8cdf9bf9f6c91162fb8dec50c259ce700f2770a", + "sha256:a8bbdb166e2fb816e43ab034c865147edafe28e1b19c72433147789ac83e2dda", + "sha256:ac786f6cb7aa10d44e9641c7a7d16d7f6e095b138795cd43503769d4154e0dc2", + "sha256:b09bc62e5193e31d7f9876220fb429ec13a6a181a24d897b9edfbbdbcd678851", + "sha256:b10556817f09d46d420edd982dd0653940b90151d0576f09143a8e773459f6fe", + "sha256:b81076552d34c27e5149a40187a8f7e2abb2d3185576a317aaf14aeeedad862a", + "sha256:bdfc54b4468ed4cd7415928cbe782f4d782722a81aeb0f81e2ddca9932632211", + "sha256:cf6e7d5fe2aeb54898df18db1baf479863eae581cce05410f61f6b4188c8ada1", + "sha256:cf98038d2abf63a1ada5730e91e84c642ba6c225b0198c3684151b1f80c5f8a6", + "sha256:d24a9e61df7a7787b338a58abfba975414937b609eb6b18973e25f573bc0eeeb", + "sha256:d74ee72b5071818a1a5dab47338e87f08a738cb938a3b0653b9e4d959ddd1fd9", + "sha256:dd16302d39c4d6f4afde80edd0c97d4db643327d355a312762ccd9bd2ca515ed", + "sha256:dd2fb11922f58df8528adfca123f6a84748ad17d066007e7ac977720063556bd", + "sha256:deac4bdafa19bbb89edfb73b19f7f69a52d0b5bd3bb0c4ad404c1bbfd7b4b7fd", + "sha256:e03c3b8cc7883a54c3f34a6a135c4a17bc9088a33f36796acdb47162791b02f6", + "sha256:e1ec8a9ee0987d4524ffd6299e778c16cc35fef6d1a2764e609f90962f0b293a", + "sha256:e8603e691580487f11306ecb066c76f1f4a8b54fb3bdb23fa40643a059509366", + "sha256:f444762fed1bc1fd75187ef14a20ed900c1fbb245d45be9e834b822a0223bc81", + "sha256:f63600ec06982cdf480899026f4fda622776f5fabed9a869fdb32d72bc17e99a", + "sha256:fb62d517a516128bacf08cb6a86ecd39fb06d08e7c4980251f5d5601d29989ba" + ], + "version": "==3.17.6" }, "six": { "hashes": [ @@ -1116,12 +1183,11 @@ }, "social-auth-app-django": { "hashes": [ - "sha256:2c69e57df0b30c9c1823519c5f1992cbe4f3f98fdc7d95c840e091a752708840", - "sha256:567ad0e028311541d7dfed51d3bf2c60440a6fd236d5d4d06c5a618b3d6c57c5", - "sha256:df5212370bd250108987c4748419a1a1d0cec750878856c2644c36aaa0fd3e58" + "sha256:52241a25445a010ab1c108bafff21fc5522d5c8cd0d48a92c39c7371824b065d", + "sha256:b6e3132ce087cdd6e1707aeb1b588be41d318408fcf6395435da0bc6fe9a9795" ], "index": "pypi", - "version": "==4.0" + "version": "==5.0" }, "social-auth-core": { "extras": [ @@ -1156,10 +1222,10 @@ "yaml" ], "hashes": [ - "sha256:41aa40981cddd7ec4d1fabeae7c38d271601b306386bd05b5c3bcae13e5aeb20", - "sha256:f83cac08454f225a34a305daa20e2110d5e6335135d505f93bc66583a5f9c10d" + "sha256:26141c9cf2d5904a2228d3f5d45f8a46a3f3f2f0fbb4c33b4a1c1ddca9f31348", + "sha256:d64c9f6712918a3d90ec5d71b44b8bab1083e3609e4844ad2be80eb633e097ed" ], - "version": "==3.0.0" + "version": "==3.1.0" }, "tenant-schemas-celery": { "hashes": [ @@ -1217,11 +1283,11 @@ }, "unicef-attachments": { "hashes": [ - "sha256:4a62e9335b231a1360d2a2bf9664e3999e8261005839e7e3811f38fe21ba3e3e", - "sha256:73e2fef89895ce5c8bf17c5fd2e0fd39d191b628d600fdf195daa8f56ff5a906" + "sha256:6453bc7a4eda14c41f327a35f7e58c298c30a27e387c74fe02cd4eb941892482", + "sha256:eb69e528fbddabb1a4eba21435ce4867a5c6c4a21de62b27b0aa56891141ae81" ], "index": "pypi", - "version": "==0.9.0" + "version": "==0.10.1" }, "unicef-djangolib": { "hashes": [ @@ -1233,11 +1299,11 @@ }, "unicef-locations": { "hashes": [ - "sha256:61363692737bbecb3d50efd03d61ab86746a2876a366241c5a354548951040ee", - "sha256:a83898767dacc675dc2bd9dc31be029346e1ae9f13dce925f1de6202c5768887" + "sha256:87432b120d10f33746bb8e12f38fedc999ea0043be2d581a96a4632c2ffc0e58", + "sha256:bdd0f3c722d79c1aca41f6866f33a09ea9d126e2a9b12e8fb3524c5d40909a60" ], "index": "pypi", - "version": "==3.0" + "version": "==3.1" }, "unicef-notification": { "hashes": [ @@ -1286,10 +1352,10 @@ }, "uritemplate": { "hashes": [ - "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f", - "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae" + "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", + "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" ], - "version": "==3.0.1" + "version": "==4.1.1" }, "urllib3": { "hashes": [ @@ -1373,66 +1439,78 @@ }, "backports.entry-points-selectable": { "hashes": [ - "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a", - "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc" + "sha256:7fceed9532a7aa2bd888654a7314f864a3c16a4e710b34a58cfc0f08114c663b", + "sha256:914b21a479fde881635f7af5adc7f6e38d6b274be32269070c53b698c60d5386" ], - "version": "==1.1.0" + "version": "==1.1.1" }, "certifi": { "hashes": [ - "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", - "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" + "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", + "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" ], - "version": "==2021.5.30" + "version": "==2021.10.8" }, "charset-normalizer": { "hashes": [ - "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6", - "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f" + "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721", + "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c" ], "markers": "python_version >= '3'", - "version": "==2.0.6" + "version": "==2.0.9" }, "coverage": { "hashes": [ - "sha256:08fd55d2e00dac4c18a2fa26281076035ec86e764acdc198b9185ce749ada58f", - "sha256:11ce082eb0f7c2bbfe96f6c8bcc3a339daac57de4dc0f3186069ec5c58da911c", - "sha256:17983f6ccc47f4864fd16d20ff677782b23d1207bf222d10e4d676e4636b0872", - "sha256:25df2bc53a954ba2ccf230fa274d1de341f6aa633d857d75e5731365f7181749", - "sha256:274a612f67f931307706b60700f1e4cf80e1d79dff6c282fc9301e4565e78724", - "sha256:3dfb23cc180b674a11a559183dff9655beb9da03088f3fe3c4f3a6d200c86f05", - "sha256:43bada49697a62ffa0283c7f01bbc76aac562c37d4bb6c45d56dd008d841194e", - "sha256:4865dc4a7a566147cbdc2b2f033a6cccc99a7dcc89995137765c384f6c73110b", - "sha256:581fddd2f883379bd5af51da9233e0396b6519f3d3eeae4fb88867473be6d56e", - "sha256:5c191e01b23e760338f19d8ba2470c0dad44c8b45e41ac043b2db84efc62f695", - "sha256:6e216e4021c934246c308fd3e0d739d9fa8a3f4ea414f584ab90ef9c1592f282", - "sha256:72f8c99f1527c5a8ee77c890ea810e26b39fd0b4c2dffc062e20a05b2cca60ef", - "sha256:7593a49300489d064ebb6c58539f52cbbc4a2e6a4385de5e92cae1563f88a425", - "sha256:7844a8c6a0fee401edbf578713c2473e020759267c40261b294036f9d3eb6a2d", - "sha256:7af2f8e7bb54ace984de790e897f858e88068d8fbc46c9490b7c19c59cf51822", - "sha256:7dbda34e8e26bd86606ba8a9c13ccb114802e01758a3d0a75652ffc59a573220", - "sha256:82b58d37c47d93a171be9b5744bcc96a0012cbf53d5622b29a49e6be2097edd7", - "sha256:8305e14112efb74d0b5fec4df6e41cafde615c2392a7e51c84013cafe945842c", - "sha256:8426fec5ad5a6e8217921716b504e9b6e1166dc147e8443b4855e329db686282", - "sha256:88f1810eb942e7063d051d87aaaa113eb5fd5a7fd2cda03a972de57695b8bb1a", - "sha256:8da0c4a26a831b392deaba5fdd0cd7838d173b47ce2ec3d0f37be630cb09ef6e", - "sha256:a9dbfcbc56d8de5580483cf2caff6a59c64d3e88836cbe5fb5c20c05c29a8808", - "sha256:aa5d4d43fa18cc9d0c6e02a83de0b9729b5451a9066574bd276481474f0a53ab", - "sha256:adb0f4c3c8ba8104378518a1954cbf3d891a22c13fd0e0bf135391835f44f288", - "sha256:b4ee5815c776dfa3958ba71c7cd4cdd8eb40d79358a18352feb19562fe4408c4", - "sha256:b5dd5ae0a9cd55d71f1335c331e9625382239b8cede818fb62d8d2702336dbf8", - "sha256:b78dd3eeb8f5ff26d2113c41836bac04a9ea91be54c346826b54a373133c8c53", - "sha256:bea681309bdd88dd1283a8ba834632c43da376d9bce05820826090aad80c0126", - "sha256:befb5ffa9faabef6dadc42622c73de168001425258f0b7e402a2934574e7a04b", - "sha256:d795a2c92fe8cb31f6e9cd627ee4f39b64eb66bf47d89d8fcf7cb3d17031c887", - "sha256:d82cbef1220703ce56822be7fbddb40736fc1a928ac893472df8aff7421ae0aa", - "sha256:e63490e8a6675cee7a71393ee074586f7eeaf0e9341afd006c5d6f7eec7c16d7", - "sha256:e735ab8547d8a1fe8e58dd765d6f27ac539b395f52160d767b7189f379f9be7a", - "sha256:fa816e97cfe1f691423078dffa39a18106c176f28008db017b3ce3e947c34aa5", - "sha256:fff04bfefb879edcf616f1ce5ea6f4a693b5976bdc5e163f8464f349c25b59f0" - ], - "index": "pypi", - "version": "==6.0" + "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0", + "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd", + "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884", + "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48", + "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76", + "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0", + "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64", + "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685", + "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47", + "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d", + "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840", + "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f", + "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971", + "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c", + "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a", + "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de", + "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17", + "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4", + "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521", + "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57", + "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b", + "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282", + "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644", + "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475", + "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d", + "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da", + "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953", + "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2", + "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e", + "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c", + "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc", + "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64", + "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74", + "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617", + "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3", + "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d", + "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa", + "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739", + "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8", + "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8", + "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781", + "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58", + "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9", + "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c", + "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd", + "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e", + "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49" + ], + "index": "pypi", + "version": "==6.2" }, "decorator": { "hashes": [ @@ -1443,10 +1521,10 @@ }, "distlib": { "hashes": [ - "sha256:c8b54e8454e5bf6237cc84c20e8264c3e991e824ef27e8f1e81049867d861e31", - "sha256:d982d0751ff6eaaab5e2ec8e691d949ee80eddf01a62eaa96ddb11531fe16b05" + "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b", + "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579" ], - "version": "==0.3.3" + "version": "==0.3.4" }, "docutils": { "hashes": [ @@ -1457,18 +1535,18 @@ }, "factory-boy": { "hashes": [ - "sha256:1d3db4b44b8c8c54cdd8b83ae4bdb9aeb121e464400035f1f03ae0e1eade56a4", - "sha256:401cc00ff339a022f84d64a4339503d1689e8263a4478d876e58a3295b155c5b" + "sha256:a98d277b0c047c75eb6e4ab8508a7f81fb03d2cb21986f627913546ef7a2a55e", + "sha256:eb02a7dd1b577ef606b75a253b9818e6f9eaf996d94449c9d5ebb124f90dc795" ], "index": "pypi", - "version": "==3.2.0" + "version": "==3.2.1" }, "faker": { "hashes": [ - "sha256:bb10913b9d3ac2aa37180f816c82040e81f9e0c32cb08445533f293cec8930bf", - "sha256:d70b375d0af0e4c3abd594003691a1055a96281a414884e623d27bccc7d781da" + "sha256:3163c84866cf118ac5329a802e046b0f729528ce62ebb2806b626e0badbb6ff3", + "sha256:530690ad12a2a054071af95fc8a354c5fd57b5e7707053a9662f40f14a87b68e" ], - "version": "==8.16.0" + "version": "==10.0.0" }, "fancycompleter": { "hashes": [ @@ -1479,18 +1557,18 @@ }, "filelock": { "hashes": [ - "sha256:8c7eab13dc442dc249e95158bcc12dec724465919bdc9831fdbf0660f03d1785", - "sha256:bbc6a0382fe8ec4744ecdf6683a2e07f65eb10ff1aff53fc02a202565446cde0" + "sha256:2e139a228bcf56dd8b2274a65174d005c4a6b68540ee0bdbb92c76f43f29f7e8", + "sha256:93d512b32a23baf4cac44ffd72ccf70732aeff7b8050fcaf6d3ec406d954baf4" ], - "version": "==3.3.0" + "version": "==3.4.0" }, "flake8": { "hashes": [ - "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b", - "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907" + "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d", + "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d" ], "index": "pypi", - "version": "==3.9.2" + "version": "==4.0.1" }, "freezegun": { "hashes": [ @@ -1502,54 +1580,55 @@ }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3'", - "version": "==3.2" + "version": "==3.3" }, "imagesize": { "hashes": [ - "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", - "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c", + "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d" ], - "version": "==1.2.0" + "version": "==1.3.0" }, "ipython": { "hashes": [ - "sha256:2097be5c814d1b974aea57673176a924c4c8c9583890e7a5f082f547b9975b11", - "sha256:f16148f9163e1e526f1008d7c8d966d9c15600ca20d1a754287cf96d00ba6f1d" + "sha256:cb6aef731bf708a7727ab6cde8df87f0281b1427d41e65d62d4b68934fa54e97", + "sha256:fc60ef843e0863dd4e24ab2bb5698f071031332801ecf8d1aeb4fb622056545c" ], "index": "pypi", - "version": "==7.28.0" + "version": "==7.30.1" }, "isort": { "hashes": [ - "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899", - "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2" + "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7", + "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951" ], "index": "pypi", - "version": "==5.9.3" + "version": "==5.10.1" }, "jedi": { "hashes": [ - "sha256:18456d83f65f400ab0c2d3319e48520420ef43b23a086fdc05dff34132f0fb93", - "sha256:92550a404bad8afed881a137ec9a461fed49eca661414be45059329614ed0707" + "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d", + "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab" ], - "version": "==0.18.0" + "version": "==0.18.1" }, "jinja2": { "hashes": [ - "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4", - "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4" + "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", + "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7" ], - "version": "==3.0.1" + "version": "==3.0.3" }, "markupsafe": { "hashes": [ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", + "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194", "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", @@ -1557,6 +1636,7 @@ "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", + "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a", "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", @@ -1564,27 +1644,36 @@ "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", + "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047", "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", + "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b", "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", + "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1", "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", + "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee", + "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f", "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", + "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86", + "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6", "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", + "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e", "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", + "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f", "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d", @@ -1592,10 +1681,14 @@ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066", "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c", "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1", + "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a", + "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207", "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f", "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53", + "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd", "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134", "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85", + "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9", "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5", "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94", "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509", @@ -1705,17 +1798,17 @@ }, "packaging": { "hashes": [ - "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", - "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" + "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", + "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" ], - "version": "==21.0" + "version": "==21.3" }, "parso": { "hashes": [ - "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398", - "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22" + "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", + "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" ], - "version": "==0.8.2" + "version": "==0.8.3" }, "pdbpp": { "hashes": [ @@ -1756,10 +1849,10 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c", - "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c" + "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6", + "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506" ], - "version": "==3.0.20" + "version": "==3.0.24" }, "ptyprocess": { "hashes": [ @@ -1770,24 +1863,24 @@ }, "py": { "hashes": [ - "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", - "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" + "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", + "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" ], - "version": "==1.10.0" + "version": "==1.11.0" }, "pycodestyle": { "hashes": [ - "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068", - "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef" + "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20", + "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f" ], - "version": "==2.7.0" + "version": "==2.8.0" }, "pyflakes": { "hashes": [ - "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3", - "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db" + "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c", + "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e" ], - "version": "==2.3.1" + "version": "==2.4.0" }, "pygments": { "hashes": [ @@ -1798,10 +1891,10 @@ }, "pyparsing": { "hashes": [ - "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", - "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4", + "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81" ], - "version": "==2.4.7" + "version": "==3.0.6" }, "pyrepl": { "hashes": [ @@ -1868,11 +1961,11 @@ }, "responses": { "hashes": [ - "sha256:57bab4e9d4d65f31ea5caf9de62095032c4d81f591a8fac2f5858f7777b8567b", - "sha256:93f774a762ee0e27c0d9d7e06227aeda9ff9f5f69392f72bb6c6b73f8763563e" + "sha256:a2e3aca2a8277e61257cd3b1c154b1dd0d782b1ae3d38b7fa37cbe3feb531791", + "sha256:f358ef75e8bf431b0aa203cc62625c3a1c80a600dbe9de91b944bf4e9c600b92" ], "index": "pypi", - "version": "==0.14.0" + "version": "==0.16.0" }, "six": { "hashes": [ @@ -1883,18 +1976,18 @@ }, "snowballstemmer": { "hashes": [ - "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2", - "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914" + "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", + "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" ], - "version": "==2.1.0" + "version": "==2.2.0" }, "sphinx": { "hashes": [ - "sha256:94078db9184491e15bce0a56d9186e0aec95f16ac20b12d00e06d4e36f1058a6", - "sha256:98a535c62a4fcfcc362528592f69b26f7caec587d32cd55688db580be0287ae0" + "sha256:048dac56039a5713f47a554589dc98a442b39226a2b9ed7f82797fcb2fe9253f", + "sha256:32a5b3e9a1b176cc25ed048557d4d3d01af635e6b76c5bc7a43b0a34447fbd45" ], "index": "pypi", - "version": "==4.2.0" + "version": "==4.3.1" }, "sphinxcontrib-applehelp": { "hashes": [ @@ -1962,10 +2055,10 @@ }, "traitlets": { "hashes": [ - "sha256:03f172516916220b58c9f19d7f854734136dd9528103d04e9bf139a92c9f54c4", - "sha256:bd382d7ea181fbbcce157c133db9a829ce06edffe097bcf3ab945b435452b46d" + "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7", + "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033" ], - "version": "==5.1.0" + "version": "==5.1.1" }, "urllib3": { "hashes": [ @@ -1984,10 +2077,10 @@ }, "virtualenv": { "hashes": [ - "sha256:10062e34c204b5e4ec5f62e6ef2473f8ba76513a9a617e873f1f8fb4a519d300", - "sha256:bcc17f0b3a29670dd777d6f0755a4c04f28815395bca279cdcb213b97199a6b8" + "sha256:4b02e52a624336eece99c96e3ab7111f469c24ba226a53ec474e8e787b365814", + "sha256:576d05b46eace16a9c348085f7d0dc8ef28713a2cabaa1cf0aea41e8f12c9218" ], - "version": "==20.8.1" + "version": "==20.10.0" }, "wcwidth": { "hashes": [ @@ -2004,52 +2097,137 @@ }, "wrapt": { "hashes": [ - "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" - ], - "version": "==1.12.1" + "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179", + "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096", + "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374", + "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df", + "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185", + "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785", + "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7", + "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909", + "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918", + "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33", + "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068", + "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829", + "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af", + "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79", + "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce", + "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc", + "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36", + "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade", + "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca", + "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32", + "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125", + "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e", + "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709", + "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f", + "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b", + "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb", + "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb", + "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489", + "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640", + "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb", + "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851", + "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d", + "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44", + "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13", + "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2", + "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb", + "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b", + "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9", + "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755", + "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c", + "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a", + "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf", + "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3", + "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229", + "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e", + "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de", + "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554", + "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10", + "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80", + "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056", + "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea" + ], + "version": "==1.13.3" }, "yarl": { "hashes": [ - "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e", - "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434", - "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366", - "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3", - "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec", - "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959", - "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e", - "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c", - "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6", - "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a", - "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6", - "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424", - "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e", - "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f", - "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50", - "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2", - "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc", - "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4", - "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970", - "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10", - "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0", - "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406", - "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896", - "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643", - "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721", - "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478", - "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724", - "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e", - "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8", - "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96", - "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25", - "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76", - "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2", - "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2", - "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c", - "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a", - "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71" + "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", + "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8", + "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e", + "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746", + "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98", + "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125", + "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d", + "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d", + "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986", + "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d", + "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec", + "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8", + "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee", + "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3", + "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1", + "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd", + "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b", + "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de", + "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0", + "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8", + "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6", + "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245", + "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23", + "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332", + "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1", + "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c", + "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4", + "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0", + "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8", + "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832", + "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58", + "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6", + "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1", + "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52", + "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92", + "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185", + "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d", + "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d", + "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b", + "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739", + "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05", + "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63", + "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d", + "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa", + "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913", + "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe", + "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b", + "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b", + "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656", + "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1", + "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4", + "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e", + "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63", + "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271", + "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed", + "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d", + "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda", + "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265", + "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f", + "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c", + "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba", + "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c", + "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b", + "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523", + "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a", + "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef", + "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95", + "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72", + "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794", + "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41", + "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576", + "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59" ], "markers": "python_version >= '3.6'", - "version": "==1.6.3" + "version": "==1.7.2" } } } diff --git a/src/etools/libraries/locations/tests/test_views.py b/src/etools/libraries/locations/tests/test_views.py index 5ccfd5d9b4..e0e0f0c52e 100644 --- a/src/etools/libraries/locations/tests/test_views.py +++ b/src/etools/libraries/locations/tests/test_views.py @@ -16,7 +16,7 @@ def setUpTestData(cls): cls.locations.append(cls.parent) # heavy_detail_expected_keys are the keys that should be in response.data.keys() cls.heavy_detail_expected_keys = sorted( - ('id', 'name', 'p_code', 'gateway', 'parent', 'geo_point') + ('id', 'name', 'name_display', 'p_code', 'gateway', 'parent', 'geo_point') ) def test_api_locationtypes_list(self): @@ -26,7 +26,7 @@ def test_api_locationtypes_list(self): def test_api_location_light_list(self): response = self.forced_auth_req('get', reverse('locations-light-list'), user=self.unicef_staff) self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(sorted(response.data[0].keys()), ["gateway", "id", "name", "p_code", "parent"]) + self.assertEqual(sorted(response.data[0].keys()), ["gateway", "id", "name", "name_display", "p_code", "parent"]) # sort the expected locations by name, the same way the API results are sorted self.locations.sort(key=lambda location: location.name) @@ -34,14 +34,14 @@ def test_api_location_light_list(self): location = self.locations[i] data = response.data[i] if location.parent: - self.assertEqual(data["name"], '{} [{} - {}] -- {}'.format( + self.assertEqual(data["name"], '{} ({}: {}) -- {}'.format( location.name, location.gateway.name, location.p_code, location.parent.name )) else: - self.assertEqual(data["name"], '{} [{} - {}]'.format( + self.assertEqual(data["name"], '{} ({}: {})'.format( location.name, location.gateway.name, location.p_code, @@ -117,5 +117,5 @@ def test_api_location_autocomplete(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 6) - self.assertEqual(sorted(response.data[0].keys()), ["gateway", "id", "name", "p_code", "parent"]) + self.assertEqual(sorted(response.data[0].keys()), ["gateway", "id", "name", "name_display", "p_code", "parent"]) self.assertIn("Loc", response.data[0]["name"]) From b78160af6a7283113de05a4ed883e3091da189e4 Mon Sep 17 00:00:00 2001 From: Domenico Date: Wed, 24 Nov 2021 00:26:01 -0600 Subject: [PATCH 08/39] 26702 added ip address field --- src/etools/applications/attachments/admin.py | 21 +++++++++++++++++++ .../0019_attachmentflat_ip_address.py | 18 ++++++++++++++++ src/etools/applications/attachments/models.py | 1 + .../attachments/tests/test_views.py | 1 + src/etools/applications/attachments/utils.py | 1 + 5 files changed, 42 insertions(+) create mode 100644 src/etools/applications/attachments/admin.py create mode 100644 src/etools/applications/attachments/migrations/0019_attachmentflat_ip_address.py diff --git a/src/etools/applications/attachments/admin.py b/src/etools/applications/attachments/admin.py new file mode 100644 index 0000000000..c2431ed5a8 --- /dev/null +++ b/src/etools/applications/attachments/admin.py @@ -0,0 +1,21 @@ +from django.contrib import admin + +from etools.applications.attachments.models import AttachmentFlat + + +@admin.register(AttachmentFlat) +class AttachmentAdmin(admin.ModelAdmin): + list_display = [ + 'partner', + 'partner_type', + 'vendor_number', + 'pd_ssfa', + 'pd_ssfa_number', + 'agreement_reference_number', + 'file_type', + 'file_link', + 'filename', + 'uploaded_by', + 'ip_address', + ] + list_filter = ['file_type', 'partner', ] diff --git a/src/etools/applications/attachments/migrations/0019_attachmentflat_ip_address.py b/src/etools/applications/attachments/migrations/0019_attachmentflat_ip_address.py new file mode 100644 index 0000000000..693250f471 --- /dev/null +++ b/src/etools/applications/attachments/migrations/0019_attachmentflat_ip_address.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-11-24 00:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('attachments', '0018_remove_attachmentflat_created'), + ] + + operations = [ + migrations.AddField( + model_name='attachmentflat', + name='ip_address', + field=models.GenericIPAddressField(default='0.0.0.0'), + ), + ] diff --git a/src/etools/applications/attachments/models.py b/src/etools/applications/attachments/models.py index a12a8fb358..ae6946b814 100644 --- a/src/etools/applications/attachments/models.py +++ b/src/etools/applications/attachments/models.py @@ -78,6 +78,7 @@ class AttachmentFlat(models.Model): verbose_name=_('Created'), null=True, ) + ip_address = models.GenericIPAddressField(default='0.0.0.0') objects = AttachmentFlatManager() diff --git a/src/etools/applications/attachments/tests/test_views.py b/src/etools/applications/attachments/tests/test_views.py index bd37f1902e..1acd6a8be5 100644 --- a/src/etools/applications/attachments/tests/test_views.py +++ b/src/etools/applications/attachments/tests/test_views.py @@ -102,6 +102,7 @@ def assert_keys(self, response): "created", "attachment", "source", + "ip_address" ] for row in response.data: self.assertCountEqual(list(row.keys()), expected_keys) diff --git a/src/etools/applications/attachments/utils.py b/src/etools/applications/attachments/utils.py index fe898e8a4d..f9b19ae257 100644 --- a/src/etools/applications/attachments/utils.py +++ b/src/etools/applications/attachments/utils.py @@ -172,6 +172,7 @@ def denormalize_attachment(attachment): "file_link": attachment.file_link, "filename": attachment.filename, "uploaded_by": uploaded_by, + "ip_address": attachment.ip_address, "source": source, "created": attachment.created, } From 94d5d4054afae460debc506ad8ff8e35ed0878c7 Mon Sep 17 00:00:00 2001 From: Domenico Date: Fri, 17 Dec 2021 09:56:24 -0600 Subject: [PATCH 09/39] fix russian template --- src/etools/applications/partners/templates/pca/russian_pdf.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/etools/applications/partners/templates/pca/russian_pdf.html b/src/etools/applications/partners/templates/pca/russian_pdf.html index 5af3aeb669..549e5670d2 100644 --- a/src/etools/applications/partners/templates/pca/russian_pdf.html +++ b/src/etools/applications/partners/templates/pca/russian_pdf.html @@ -158,7 +158,6 @@ {% endblock %} {% endblock %} -{% load staticfiles %} {% block content %} {% if error %} From 3e2ccc8a9f9f0280065d7f74772125d68d9a5a14 Mon Sep 17 00:00:00 2001 From: Domenico Date: Mon, 20 Dec 2021 08:52:23 -0600 Subject: [PATCH 10/39] 5556 sections --- src/etools/applications/management/views/sections.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etools/applications/management/views/sections.py b/src/etools/applications/management/views/sections.py index 867fd4c8de..0644493458 100644 --- a/src/etools/applications/management/views/sections.py +++ b/src/etools/applications/management/views/sections.py @@ -57,11 +57,11 @@ def close(self, request): try: old_section = request.data['old_section'] objects_dict = request.data['new_sections'] - logger.info('Section Migrate', objects_dict) + sections = SectionHandler.close(old_section, objects_dict) + except (KeyError, MigrationException): return Response(_('Unable to unpack'), status=status.HTTP_400_BAD_REQUEST) - sections = SectionHandler.close(old_section, objects_dict) data = [{'id': section.id, 'name': section.name} for section in sections] return Response(data) From 33d89dcc706b4fa3eab5f594f5373cfce851ae9e Mon Sep 17 00:00:00 2001 From: blu Date: Wed, 29 Dec 2021 15:56:31 +0200 Subject: [PATCH 11/39] fix for Assessment has no assessor error (sentry issue # ETOOLS-PROD-EJ) --- src/etools/applications/psea/models.py | 2 +- .../applications/psea/tests/test_views.py | 40 ++++++++++++++----- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/etools/applications/psea/models.py b/src/etools/applications/psea/models.py index 5db7ab1e3c..3569af0346 100644 --- a/src/etools/applications/psea/models.py +++ b/src/etools/applications/psea/models.py @@ -283,7 +283,7 @@ def get_mail_context(self, user): "assessment_date": str(self.assessment_date), "assessment_type": self.get_assessment_type_display(), "assessment_ingo_reason": self.get_assessment_ingo_reason_display(), - "assessor": str(self.assessor), + "assessor": str(getattr(self, 'assessor', '')), "focal_points": ", ".join(f"{fp.get_full_name()} ({fp.email})" for fp in self.focal_points.all()), "nfr_attachment": nfr_attachment } diff --git a/src/etools/applications/psea/tests/test_views.py b/src/etools/applications/psea/tests/test_views.py index 391e41422b..3f7d67b392 100644 --- a/src/etools/applications/psea/tests/test_views.py +++ b/src/etools/applications/psea/tests/test_views.py @@ -1081,16 +1081,7 @@ def test_action_point_added(self): 'post', reverse("psea:action-points-list", args=[assessment.pk]), user=self.focal_user, - data={ - 'description': fuzzy.FuzzyText(length=100).fuzz(), - 'due_date': fuzzy.FuzzyDate( - timezone.now().date(), - timezone.now().date() + datetime.timedelta(days=5), - ).fuzz(), - 'assigned_to': self.unicef_user.pk, - 'office': self.focal_user.profile.tenant_profile.office.pk, - 'section': SectionFactory().pk, - } + data=self._get_post_payload() ) self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1098,6 +1089,35 @@ def test_action_point_added(self): self.assertIsNotNone(assessment.action_points.first().partner) self.assertTrue(mock_send) + @override_settings(UNICEF_USER_EMAIL="@example.com") + def test_action_point_added_no_assessor(self): + assessment = AssessmentFactory() + mock_send = Mock() + with patch(self.send_path, mock_send): + response = self.forced_auth_req( + 'post', + reverse("psea:action-points-list", args=[assessment.pk]), + user=self.focal_user, + data=self._get_post_payload() + ) + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(assessment.action_points.count(), 1) + self.assertIsNotNone(assessment.action_points.first().partner) + self.assertTrue(mock_send) + + def _get_post_payload(self): + return { + 'description': fuzzy.FuzzyText(length=100).fuzz(), + 'due_date': fuzzy.FuzzyDate( + timezone.now().date(), + timezone.now().date() + datetime.timedelta(days=5) + ).fuzz(), + 'assigned_to': self.unicef_user.pk, + 'office': self.focal_user.profile.tenant_profile.office.pk, + 'section': SectionFactory().pk, + } + def _test_action_point_editable(self, action_point, user, editable=True): assessment = action_point.psea_assessment From b71b6a16bbbef34ef32dfb633c727cd1f2f64dc6 Mon Sep 17 00:00:00 2001 From: Domenico Date: Fri, 10 Dec 2021 09:05:06 -0600 Subject: [PATCH 12/39] addess warnings --- .../applications/action_points/__init__.py | 1 - .../action_points/categories/__init__.py | 1 - src/etools/applications/action_points/urls.py | 4 +- src/etools/applications/audit/__init__.py | 1 - .../audit/purchase_order/__init__.py | 1 - src/etools/applications/audit/urls.py | 20 +- src/etools/applications/core/__init__.py | 1 - .../applications/environment/urls_v2.py | 10 +- .../field_monitoring/analyze/__init__.py | 1 - .../field_monitoring/analyze/urls.py | 25 +- .../data_collection/__init__.py | 1 - .../field_monitoring/data_collection/urls.py | 10 +- .../field_monitoring/fm_settings/__init__.py | 1 - .../field_monitoring/fm_settings/urls.py | 14 +- .../field_monitoring/planning/__init__.py | 1 - .../field_monitoring/planning/urls.py | 6 +- .../applications/field_monitoring/urls.py | 10 +- src/etools/applications/funds/urls.py | 41 ++- src/etools/applications/hact/urls.py | 9 +- src/etools/applications/management/urls.py | 35 +- .../applications/management/urls_gis.py | 10 +- src/etools/applications/partners/__init__.py | 1 - src/etools/applications/partners/prp_urls.py | 20 +- src/etools/applications/partners/urls.py | 7 +- src/etools/applications/partners/urls_v2.py | 312 +++++++++--------- src/etools/applications/psea/__init__.py | 1 - src/etools/applications/publics/urls.py | 26 +- src/etools/applications/reports/__init__.py | 1 - src/etools/applications/reports/urls_v2.py | 66 ++-- src/etools/applications/t2f/urls.py | 40 +-- src/etools/applications/tpm/__init__.py | 1 - src/etools/applications/tpm/models.py | 8 +- src/etools/applications/tpm/urls.py | 18 +- src/etools/applications/users/serializers.py | 6 +- src/etools/applications/users/urls.py | 12 +- src/etools/applications/users/urls_v2.py | 14 +- src/etools/applications/users/urls_v3.py | 16 +- src/etools/config/settings/base.py | 2 +- src/etools/config/urls.py | 86 ++--- src/etools/libraries/azure_graph_api/tasks.py | 10 +- src/etools/libraries/locations/urls.py | 6 +- src/etools/libraries/monitoring/urls.py | 6 +- 42 files changed, 421 insertions(+), 441 deletions(-) diff --git a/src/etools/applications/action_points/__init__.py b/src/etools/applications/action_points/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/action_points/__init__.py +++ b/src/etools/applications/action_points/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/action_points/categories/__init__.py b/src/etools/applications/action_points/categories/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/action_points/categories/__init__.py +++ b/src/etools/applications/action_points/categories/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/action_points/urls.py b/src/etools/applications/action_points/urls.py index ac8c1c1343..e7f935acda 100644 --- a/src/etools/applications/action_points/urls.py +++ b/src/etools/applications/action_points/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework_nested import routers @@ -12,5 +12,5 @@ urlpatterns = [ - url(r'^', include(action_points_api.urls)), + re_path(r'^', include(action_points_api.urls)), ] diff --git a/src/etools/applications/audit/__init__.py b/src/etools/applications/audit/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/audit/__init__.py +++ b/src/etools/applications/audit/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/audit/purchase_order/__init__.py b/src/etools/applications/audit/purchase_order/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/audit/purchase_order/__init__.py +++ b/src/etools/applications/audit/purchase_order/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/audit/urls.py b/src/etools/applications/audit/urls.py index 0e73161b9a..982bb0c12e 100644 --- a/src/etools/applications/audit/urls.py +++ b/src/etools/applications/audit/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework_nested import routers from unicef_restlib.routers import NestedComplexRouter @@ -27,31 +27,31 @@ app_name = 'audit' urlpatterns = [ - url(r'^', include(auditor_staffmember_api.urls)), - url(r'^', include(engagement_action_points_api.urls)), - url(r'^', include(attachments_api.urls)), - url(r'^', include(root_api.urls)), - url( + re_path(r'^', include(auditor_staffmember_api.urls)), + re_path(r'^', include(engagement_action_points_api.urls)), + re_path(r'^', include(attachments_api.urls)), + re_path(r'^', include(root_api.urls)), + re_path( r'^engagement/(?P\d+)/links', view=views.EngagementAttachmentLinksView.as_view(), name='engagement-links' ), - url( + re_path( r'^spot-check/(?P\d+)/links', view=views.SpotCheckAttachmentLinksView.as_view(), name='spot-check-links' ), - url( + re_path( r'^micro-assessment/(?P\d+)/links', view=views.MicroAssessmentAttachmentLinksView.as_view(), name='micro-assessment-links' ), - url( + re_path( r'^audit/(?P\d+)/links', view=views.AuditAttachmentLinksView.as_view(), name='audit-links' ), - url( + re_path( r'^special-audit/(?P\d+)/links', view=views.SpecialAuditAttachmentLinksView.as_view(), name='special-audit-links' diff --git a/src/etools/applications/core/__init__.py b/src/etools/applications/core/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/core/__init__.py +++ b/src/etools/applications/core/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/environment/urls_v2.py b/src/etools/applications/environment/urls_v2.py index 09477fbd0b..01c56b3c10 100644 --- a/src/etools/applications/environment/urls_v2.py +++ b/src/etools/applications/environment/urls_v2.py @@ -1,12 +1,10 @@ - -from django.conf.urls import url +from django.urls import re_path from etools.applications.environment.views import ActiveFlagAPIView app_name = 'environment' urlpatterns = ( - url(r'^flags/$', - view=ActiveFlagAPIView.as_view(http_method_names=['get']), - name='api-flags-list'), - + re_path(r'^flags/$', + view=ActiveFlagAPIView.as_view(http_method_names=['get']), + name='api-flags-list'), ) diff --git a/src/etools/applications/field_monitoring/analyze/__init__.py b/src/etools/applications/field_monitoring/analyze/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/field_monitoring/analyze/__init__.py +++ b/src/etools/applications/field_monitoring/analyze/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/field_monitoring/analyze/urls.py b/src/etools/applications/field_monitoring/analyze/urls.py index 410ced7778..fda1702c8b 100644 --- a/src/etools/applications/field_monitoring/analyze/urls.py +++ b/src/etools/applications/field_monitoring/analyze/urls.py @@ -1,21 +1,20 @@ -from django.conf.urls import url -from django.urls import include +from django.urls import include, re_path from etools.applications.field_monitoring.analyze import views app_name = 'field_monitoring_analyze' urlpatterns = [ - url(r'overall/$', views.OverallView.as_view(), name='overall'), - url(r'coverage/', include([ - url(r'partners/$', views.CoveragePartnersView.as_view(), name='coverage-partners'), - url(r'interventions/$', views.CoverageInterventionsView.as_view(), name='coverage-interventions'), - url(r'cp-outputs/$', views.CoverageCPOutputsView.as_view(), name='coverage-cp_outputs'), - url(r'geographic/$', views.CoverageGeographicView.as_view(), name='coverage-geographic'), + re_path(r'overall/$', views.OverallView.as_view(), name='overall'), + re_path(r'coverage/', include([ + re_path(r'partners/$', views.CoveragePartnersView.as_view(), name='coverage-partners'), + re_path(r'interventions/$', views.CoverageInterventionsView.as_view(), name='coverage-interventions'), + re_path(r'cp-outputs/$', views.CoverageCPOutputsView.as_view(), name='coverage-cp_outputs'), + re_path(r'geographic/$', views.CoverageGeographicView.as_view(), name='coverage-geographic'), ])), - url(r'hact/$', views.HACTView.as_view(), name='hact'), - url(r'issues/', include([ - url(r'partners/$', views.IssuesPartnersView.as_view(), name='issues-partners'), - url(r'cp-outputs/$', views.IssuesCPOutputsView.as_view(), name='issues-cp_outputs'), - url(r'locations/$', views.IssuesLocationsView.as_view(), name='issues-locations'), + re_path(r'hact/$', views.HACTView.as_view(), name='hact'), + re_path(r'issues/', include([ + re_path(r'partners/$', views.IssuesPartnersView.as_view(), name='issues-partners'), + re_path(r'cp-outputs/$', views.IssuesCPOutputsView.as_view(), name='issues-cp_outputs'), + re_path(r'locations/$', views.IssuesLocationsView.as_view(), name='issues-locations'), ])), ] diff --git a/src/etools/applications/field_monitoring/data_collection/__init__.py b/src/etools/applications/field_monitoring/data_collection/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/field_monitoring/data_collection/__init__.py +++ b/src/etools/applications/field_monitoring/data_collection/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/field_monitoring/data_collection/urls.py b/src/etools/applications/field_monitoring/data_collection/urls.py index 2a691d4ac6..9e31351ca2 100644 --- a/src/etools/applications/field_monitoring/data_collection/urls.py +++ b/src/etools/applications/field_monitoring/data_collection/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework_nested import routers from unicef_restlib.routers import NestedComplexRouter @@ -29,8 +29,8 @@ app_name = 'field_monitoring_data_collection' urlpatterns = [ - url(r'^', include(checklist_overall_findings_api.urls)), - url(r'^', include(checklists_api.urls)), - url(r'^', include(activities_api.urls)), - url(r'^', include(root_api.urls)), + re_path(r'^', include(checklist_overall_findings_api.urls)), + re_path(r'^', include(checklists_api.urls)), + re_path(r'^', include(activities_api.urls)), + re_path(r'^', include(root_api.urls)), ] diff --git a/src/etools/applications/field_monitoring/fm_settings/__init__.py b/src/etools/applications/field_monitoring/fm_settings/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/field_monitoring/fm_settings/__init__.py +++ b/src/etools/applications/field_monitoring/fm_settings/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/field_monitoring/fm_settings/urls.py b/src/etools/applications/field_monitoring/fm_settings/urls.py index b9a9cfb447..c7621c0308 100644 --- a/src/etools/applications/field_monitoring/fm_settings/urls.py +++ b/src/etools/applications/field_monitoring/fm_settings/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework_nested import routers from unicef_restlib.routers import NestedComplexRouter @@ -19,10 +19,10 @@ app_name = 'field_monitoring_settings' urlpatterns = [ - url(r'^interventions/(?P[0-9]+)/locations/', views.InterventionLocationsView.as_view(), - name='intervention-locations'), - url(r'^results/', views.ResultsView.as_view(), name='results-list'), - url(r'^locations/country/', views.LocationsCountryView.as_view(), name='locations-country'), - url(r'^', include(log_issues_api.urls)), - url(r'^', include(root_api.urls)), + re_path(r'^interventions/(?P[0-9]+)/locations/', views.InterventionLocationsView.as_view(), + name='intervention-locations'), + re_path(r'^results/', views.ResultsView.as_view(), name='results-list'), + re_path(r'^locations/country/', views.LocationsCountryView.as_view(), name='locations-country'), + re_path(r'^', include(log_issues_api.urls)), + re_path(r'^', include(root_api.urls)), ] diff --git a/src/etools/applications/field_monitoring/planning/__init__.py b/src/etools/applications/field_monitoring/planning/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/field_monitoring/planning/__init__.py +++ b/src/etools/applications/field_monitoring/planning/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/field_monitoring/planning/urls.py b/src/etools/applications/field_monitoring/planning/urls.py index 7a620d9e1e..e6e9e0fc46 100644 --- a/src/etools/applications/field_monitoring/planning/urls.py +++ b/src/etools/applications/field_monitoring/planning/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework_nested import routers from unicef_restlib.routers import NestedComplexRouter @@ -21,6 +21,6 @@ app_name = 'field_monitoring_planning' urlpatterns = [ - url(r'^', include(activities_api.urls)), - url(r'^', include(root_api.urls)), + re_path(r'^', include(activities_api.urls)), + re_path(r'^', include(root_api.urls)), ] diff --git a/src/etools/applications/field_monitoring/urls.py b/src/etools/applications/field_monitoring/urls.py index 5398290540..e398c47a48 100644 --- a/src/etools/applications/field_monitoring/urls.py +++ b/src/etools/applications/field_monitoring/urls.py @@ -1,8 +1,8 @@ -from django.conf.urls import include, url +from django.urls import include, re_path urlpatterns = [ - url(r'^settings/', include('etools.applications.field_monitoring.fm_settings.urls')), - url(r'^planning/', include('etools.applications.field_monitoring.planning.urls')), - url(r'^data-collection/', include('etools.applications.field_monitoring.data_collection.urls')), - url(r'^analyze/', include('etools.applications.field_monitoring.analyze.urls')), + re_path(r'^settings/', include('etools.applications.field_monitoring.fm_settings.urls')), + re_path(r'^planning/', include('etools.applications.field_monitoring.planning.urls')), + re_path(r'^data-collection/', include('etools.applications.field_monitoring.data_collection.urls')), + re_path(r'^analyze/', include('etools.applications.field_monitoring.analyze.urls')), ] diff --git a/src/etools/applications/funds/urls.py b/src/etools/applications/funds/urls.py index e430ab876e..7c775cbabc 100644 --- a/src/etools/applications/funds/urls.py +++ b/src/etools/applications/funds/urls.py @@ -1,5 +1,4 @@ - -from django.conf.urls import url +from django.urls import re_path from etools.applications.funds.views import ( DonorListAPIView, @@ -13,23 +12,23 @@ app_name = 'funds' urlpatterns = ( - url(r'^frs/$', view=FRsView.as_view(), name='frs'), - url(r'^commitment-header/$', - view=FundsCommitmentHeaderListAPIView.as_view(), - name='funds-commitment-header'), - url(r'^commitment-item/$', - view=FundsCommitmentItemListAPIView.as_view(), - name='funds-commitment-item'), - url(r'^reservation-header/$', - view=FundsReservationHeaderListAPIView.as_view(), - name='funds-reservation-header'), - url(r'^reservation-item/$', - view=FundsReservationItemListAPIView.as_view(), - name='funds-reservation-item'), - url(r'^donor/$', - view=DonorListAPIView.as_view(), - name='funds-donor'), - url(r'^grant/$', - view=GrantListAPIView.as_view(), - name='funds-grant'), + re_path(r'^frs/$', view=FRsView.as_view(), name='frs'), + re_path(r'^commitment-header/$', + view=FundsCommitmentHeaderListAPIView.as_view(), + name='funds-commitment-header'), + re_path(r'^commitment-item/$', + view=FundsCommitmentItemListAPIView.as_view(), + name='funds-commitment-item'), + re_path(r'^reservation-header/$', + view=FundsReservationHeaderListAPIView.as_view(), + name='funds-reservation-header'), + re_path(r'^reservation-item/$', + view=FundsReservationItemListAPIView.as_view(), + name='funds-reservation-item'), + re_path(r'^donor/$', + view=DonorListAPIView.as_view(), + name='funds-donor'), + re_path(r'^grant/$', + view=GrantListAPIView.as_view(), + name='funds-grant'), ) diff --git a/src/etools/applications/hact/urls.py b/src/etools/applications/hact/urls.py index 56931f4333..0e279ad05d 100644 --- a/src/etools/applications/hact/urls.py +++ b/src/etools/applications/hact/urls.py @@ -1,11 +1,10 @@ - -from django.conf.urls import url +from django.urls import re_path from etools.applications.hact.views import GraphHactExportView, GraphHactView, HactHistoryAPIView app_name = 'hact' urlpatterns = ( - url(r'^history/$', view=HactHistoryAPIView.as_view(http_method_names=['get', ]), name='hact-history'), - url(r'^graph/(?P[0-9]+)/$', view=GraphHactView.as_view(), name='hact-graph'), - url(r'^graph/(?P[0-9]+)/export/$', view=GraphHactExportView.as_view(), name='hact-graph-export'), + re_path(r'^history/$', view=HactHistoryAPIView.as_view(http_method_names=['get', ]), name='hact-history'), + re_path(r'^graph/(?P[0-9]+)/$', view=GraphHactView.as_view(), name='hact-graph'), + re_path(r'^graph/(?P[0-9]+)/export/$', view=GraphHactExportView.as_view(), name='hact-graph-export'), ) diff --git a/src/etools/applications/management/urls.py b/src/etools/applications/management/urls.py index cbc5a34c6b..5513bb05c9 100644 --- a/src/etools/applications/management/urls.py +++ b/src/etools/applications/management/urls.py @@ -1,5 +1,4 @@ -from django.conf.urls import url -from django.urls import include +from django.urls import include, re_path from rest_framework import routers @@ -24,20 +23,20 @@ urlpatterns = (( - url(r'^$', PortalDashView.as_view(), name='dashboard'), - url(r'^load-results/$', LoadResultStructure.as_view(), name='load_result_structure'), - url(r'^invalidate-cache/$', InvalidateCache.as_view(), name='invalidate_cache'), - url(r'^sync-frs/$', SyncFRs.as_view(), name='sync_frs'), - url(r'^sync-countries/$', SyncCountries.as_view(), name='sync_frs'), - url(r'^api/stats/usercounts/$', ActiveUsers.as_view(), name='stats_user_counts'), - url(r'^api/stats/agreements/$', AgreementsStatisticsView.as_view(), name='stats_agreements'), - url(r'^tasks/sync_all_users/$', SyncAllUsers.as_view(), name='tasks_sync_all_users'), - url(r'^tasks/sync_delta_users/$', SyncDeltaUsers.as_view(), name='tasks_sync_delta_users'), - url(r'^tasks/update_hact_values/$', UpdateHactValuesAPIView.as_view(), name='tasks_update_hact_values'), - url(r'^tasks/update_aggregate_hact_values/$', UpdateAggregateHactValuesAPIView.as_view(), - name='tasks_aggregate_update_hact_values'), - url(r'^tasks/send_test_email/$', TestSendEmailAPIView.as_view(), name='tasks_send_test_email'), - url(r'^reports/users/$', UsersReportView.as_view(), name='reports_users'), - url(r'^reports/pmp_indicators/$', PMPIndicatorsReportView.as_view(), name='reports_pmp_indicators'), - url(r'^', include(router.urls)), + re_path(r'^$', PortalDashView.as_view(), name='dashboard'), + re_path(r'^load-results/$', LoadResultStructure.as_view(), name='load_result_structure'), + re_path(r'^invalidate-cache/$', InvalidateCache.as_view(), name='invalidate_cache'), + re_path(r'^sync-frs/$', SyncFRs.as_view(), name='sync_frs'), + re_path(r'^sync-countries/$', SyncCountries.as_view(), name='sync_frs'), + re_path(r'^api/stats/usercounts/$', ActiveUsers.as_view(), name='stats_user_counts'), + re_path(r'^api/stats/agreements/$', AgreementsStatisticsView.as_view(), name='stats_agreements'), + re_path(r'^tasks/sync_all_users/$', SyncAllUsers.as_view(), name='tasks_sync_all_users'), + re_path(r'^tasks/sync_delta_users/$', SyncDeltaUsers.as_view(), name='tasks_sync_delta_users'), + re_path(r'^tasks/update_hact_values/$', UpdateHactValuesAPIView.as_view(), name='tasks_update_hact_values'), + re_path(r'^tasks/update_aggregate_hact_values/$', UpdateAggregateHactValuesAPIView.as_view(), + name='tasks_aggregate_update_hact_values'), + re_path(r'^tasks/send_test_email/$', TestSendEmailAPIView.as_view(), name='tasks_send_test_email'), + re_path(r'^reports/users/$', UsersReportView.as_view(), name='reports_users'), + re_path(r'^reports/pmp_indicators/$', PMPIndicatorsReportView.as_view(), name='reports_pmp_indicators'), + re_path(r'^', include(router.urls)), ), 'management') diff --git a/src/etools/applications/management/urls_gis.py b/src/etools/applications/management/urls_gis.py index e7f640219e..3ff1e909c6 100644 --- a/src/etools/applications/management/urls_gis.py +++ b/src/etools/applications/management/urls_gis.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from .views.gis_v1 import GisLocationsGeomDetailsViewset, GisLocationsGeomListViewset, GisLocationsInUseViewset @@ -6,14 +6,14 @@ urlpatterns = [ # gis URLs - url(r'^in-use/$', GisLocationsInUseViewset.as_view(), name='locations-gis-in-use'), - url(r'^locations-geom/$', GisLocationsGeomListViewset.as_view(), name='locations-gis-geom-list'), - url( + re_path(r'^in-use/$', GisLocationsInUseViewset.as_view(), name='locations-gis-in-use'), + re_path(r'^locations-geom/$', GisLocationsGeomListViewset.as_view(), name='locations-gis-geom-list'), + re_path( r'^locations-geom/pcode/(?P\w+)/$', GisLocationsGeomDetailsViewset.as_view(), name='locations-gis-get-by-pcode' ), - url( + re_path( r'^locations-geom/id/(?P\w+)/$', GisLocationsGeomDetailsViewset.as_view(), name='locations-gis-get-by-id' diff --git a/src/etools/applications/partners/__init__.py b/src/etools/applications/partners/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/partners/__init__.py +++ b/src/etools/applications/partners/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/partners/prp_urls.py b/src/etools/applications/partners/prp_urls.py index c4d636c289..d7c2b7fa0e 100644 --- a/src/etools/applications/partners/prp_urls.py +++ b/src/etools/applications/partners/prp_urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from rest_framework.urlpatterns import format_suffix_patterns @@ -6,14 +6,14 @@ app_name = 'partners' urlpatterns = ( - url(r'^interventions/$', - view=PRPInterventionListAPIView.as_view(http_method_names=['get']), - name='prp-intervention-list'), - url(r'^partners/$', - view=PRPPartnerListAPIView.as_view(http_method_names=['get']), - name='prp-partner-list'), - url(r'^get_pd_document/(?P\d+)/$', - view=PRPPDFileView.as_view(http_method_names=['get']), - name='prp-pd-document-get'), + re_path(r'^interventions/$', + view=PRPInterventionListAPIView.as_view(http_method_names=['get']), + name='prp-intervention-list'), + re_path(r'^partners/$', + view=PRPPartnerListAPIView.as_view(http_method_names=['get']), + name='prp-partner-list'), + re_path(r'^get_pd_document/(?P\d+)/$', + view=PRPPDFileView.as_view(http_method_names=['get']), + name='prp-pd-document-get'), ) urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'csv']) diff --git a/src/etools/applications/partners/urls.py b/src/etools/applications/partners/urls.py index cf400273b4..b4513dfca4 100644 --- a/src/etools/applications/partners/urls.py +++ b/src/etools/applications/partners/urls.py @@ -1,9 +1,8 @@ - -from django.conf.urls import url +from django.urls import re_path from .views.v1 import PCAPDFView, PortalLoginFailedView urlpatterns = ( - url(r'^accounts/loginfailed/(?P.+)/$', PortalLoginFailedView.as_view(), name='sociallogin_notamember'), - url(r'^agreement/(?P\d+)/pdf', PCAPDFView.as_view(), name='pca_pdf'), + re_path(r'^accounts/loginfailed/(?P.+)/$', PortalLoginFailedView.as_view(), name='sociallogin_notamember'), + re_path(r'^agreement/(?P\d+)/pdf', PCAPDFView.as_view(), name='pca_pdf'), ) diff --git a/src/etools/applications/partners/urls_v2.py b/src/etools/applications/partners/urls_v2.py index 05a15cb3d5..36227d7a5d 100644 --- a/src/etools/applications/partners/urls_v2.py +++ b/src/etools/applications/partners/urls_v2.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from rest_framework.urlpatterns import format_suffix_patterns @@ -63,180 +63,180 @@ app_name = 'partners' urlpatterns = ( - url(r'^agreements/$', view=AgreementListAPIView.as_view(), name='agreement-list'), - url(r'^agreements/(?P\d+)/$', view=AgreementDetailAPIView.as_view(http_method_names=['get', 'patch']), - name='agreement-detail'), - - url(r'^agreements/delete/(?P\d+)/$', view=AgreementDeleteView.as_view(http_method_names=['delete']), - name='agreement-delete'), - - url(r'^agreements/(?P\d+)/generate_doc/$', PCAPDFView.as_view(), name='pca_pdf'), - url(r'^agreements/amendments/$', - view=AgreementAmendmentListAPIView.as_view(), - name='agreement-amendment-list'), - url(r'^agreements/amendments/(?P\d+)/$', - view=AgreementAmendmentDeleteView.as_view(http_method_names=['delete']), - name='agreement-amendment-del'), - - url(r'^partners/$', - view=PartnerOrganizationListAPIView.as_view(http_method_names=['get']), - name='partner-list'), - url(r'^partners/not_programmatic_visit/$', - view=PartnerNotProgrammaticVisitCompliant.as_view(http_method_names=['get']), - name='partner-list-not-programmatic-visit'), - url(r'^partners/not_spot_check/$', - view=PartnerNotSpotCheckCompliant.as_view(http_method_names=['get']), - name='partner-list-not-spot-check'), - url(r'^partners/not_assurance/$', - view=PartnerNotAssuranceCompliant.as_view(http_method_names=['get']), - name='partner-list-not-assurance'), - url(r'^partners/special_audit_completed/$', - view=PartnerWithSpecialAuditCompleted.as_view(http_method_names=['get']), - name='partner-special-audit-completed'), - url(r'^partners/scheduled_audit_completed/$', - view=PartnerWithScheduledAuditCompleted.as_view(http_method_names=['get']), - name='partner-scheduled-audit-completed'), - url( + re_path(r'^agreements/$', view=AgreementListAPIView.as_view(), name='agreement-list'), + re_path(r'^agreements/(?P\d+)/$', view=AgreementDetailAPIView.as_view(http_method_names=['get', 'patch']), + name='agreement-detail'), + + re_path(r'^agreements/delete/(?P\d+)/$', view=AgreementDeleteView.as_view(http_method_names=['delete']), + name='agreement-delete'), + + re_path(r'^agreements/(?P\d+)/generate_doc/$', PCAPDFView.as_view(), name='pca_pdf'), + re_path(r'^agreements/amendments/$', + view=AgreementAmendmentListAPIView.as_view(), + name='agreement-amendment-list'), + re_path(r'^agreements/amendments/(?P\d+)/$', + view=AgreementAmendmentDeleteView.as_view(http_method_names=['delete']), + name='agreement-amendment-del'), + + re_path(r'^partners/$', + view=PartnerOrganizationListAPIView.as_view(http_method_names=['get']), + name='partner-list'), + re_path(r'^partners/not_programmatic_visit/$', + view=PartnerNotProgrammaticVisitCompliant.as_view(http_method_names=['get']), + name='partner-list-not-programmatic-visit'), + re_path(r'^partners/not_spot_check/$', + view=PartnerNotSpotCheckCompliant.as_view(http_method_names=['get']), + name='partner-list-not-spot-check'), + re_path(r'^partners/not_assurance/$', + view=PartnerNotAssuranceCompliant.as_view(http_method_names=['get']), + name='partner-list-not-assurance'), + re_path(r'^partners/special_audit_completed/$', + view=PartnerWithSpecialAuditCompleted.as_view(http_method_names=['get']), + name='partner-special-audit-completed'), + re_path(r'^partners/scheduled_audit_completed/$', + view=PartnerWithScheduledAuditCompleted.as_view(http_method_names=['get']), + name='partner-scheduled-audit-completed'), + re_path( r'^partners/planned-visits/(?P\d+)/$', view=PartnerPlannedVisitsDeleteView.as_view(http_method_names=['delete', ]), name='partner-planned-visits-del' ), - url(r'^partners/hact/$', - view=PartnerOrganizationHactAPIView.as_view(http_method_names=['get', ]), - name='partner-hact'), - url(r'^partners/hact/simple/$', - view=PartnerOrganizationSimpleHactAPIView.as_view(http_method_names=['get', ]), - name='partner-hact-simple'), - url(r'^partners/dashboard/$', - view=PartnerOrganizationDashboardAPIView.as_view(http_method_names=['get', ]), - name='partner-dashboard'), - url(r'^partners/engagements/$', - view=PlannedEngagementAPIView.as_view(http_method_names=['get', ]), - name='partner-engagements'), - url(r'^partners/(?P\d+)/$', - view=PartnerOrganizationDetailAPIView.as_view(http_method_names=['get', 'patch']), - name='partner-detail'), - url(r'^partners/delete/(?P\d+)/$', - view=PartnerOrganizationDeleteView.as_view(http_method_names=['delete']), - name='partner-delete'), - url(r'^partners/assessments/$', - view=PartnerOrganizationAssessmentListCreateView.as_view(http_method_names=['get', 'post']), - name='partner-assessment'), - url(r'^partners/assessments/(?P\d+)/$', - view=PartnerOrganizationAssessmentUpdateDeleteView.as_view(http_method_names=['delete', 'patch']), - name='partner-assessment-detail'), - url(r'^partners/add/$', view=PartnerOrganizationAddView.as_view(http_method_names=['post']), name='partner-add'), - - url(r'^partners/(?P\d+)/staff-members/$', - view=PartnerStaffMemberListAPIVIew.as_view(http_method_names=['get']), - name='partner-staff-members-list'), - - url(r'^interventions/$', - view=InterventionListAPIView.as_view(http_method_names=['get', 'post']), - name='intervention-list'), - - url(r'^interventions/applied-indicators/$', - view=InterventionWithAppliedIndicatorsView.as_view(http_method_names=['get', ]), - name='intervention-applied-indicators-list'), - - url(r'^interventions/result-links/(?P\d+)/lower-results/$', - view=InterventionLowerResultListCreateView.as_view(http_method_names=['get', 'post']), - name='intervention-lower-results-list'), - - url(r'^interventions/(?P\d+)/result-links/$', - view=InterventionResultLinkListCreateView.as_view(http_method_names=['get', 'post']), - name='intervention-result-links-list'), - - url(r'^interventions/result-links/(?P\d+)/$', - view=InterventionResultLinkUpdateView.as_view(http_method_names=['get', 'patch', 'delete']), - name='intervention-result-links-update'), - - - url(r'^interventions/lower-results/(?P\d+)/$', - view=InterventionLowerResultUpdateView.as_view(http_method_names=['get', 'patch', 'delete']), - name='intervention-lower-results-update'), - - url(r'^interventions/lower-results/(?P\d+)/indicators/$', - view=InterventionIndicatorsListView.as_view(http_method_names=['get', 'post']), - name='intervention-indicators-list'), - - url(r'^interventions/applied-indicators/(?P\d+)/$', - view=InterventionIndicatorsUpdateView.as_view(http_method_names=['get', 'patch', 'delete']), - name='intervention-indicators-update'), - - url(r'^interventions/dash/$', - view=InterventionListDashView.as_view(http_method_names=['get', 'post']), - name='intervention-list-dash'), - - url(r'^interventions/(?P\d+)/$', - view=InterventionDetailAPIView.as_view(http_method_names=['get', 'patch']), - name='intervention-detail'), - url(r'^interventions/delete/(?P\d+)/$', - view=InterventionDeleteView.as_view(http_method_names=['delete']), - name='intervention-delete'), - - url(r'^interventions/(?P\d+)/attachments/$', - view=InterventionAttachmentListCreateView.as_view(http_method_names=['get', 'post']), - name='intervention-attachment-list'), - - url(r'^interventions/attachments/(?P\d+)/$', - view=InterventionAttachmentUpdateDeleteView.as_view(http_method_names=['delete', 'patch']), - name='intervention-attachments-update'), - - url(r'^interventions/indicators/$', - view=InterventionIndicatorListAPIView.as_view(http_method_names=['get', ]), - name='intervention-indicators'), - url(r'^interventions/results/$', - view=InterventionResultListAPIView.as_view(http_method_names=['get', ]), - name='intervention-results'), - url(r'^interventions/amendments/$', - view=InterventionAmendmentListAPIView.as_view(http_method_names=['get']), - name='intervention-amendments'), - url(r'^interventions/(?P\d+)/amendments/$', - view=InterventionAmendmentListAPIView.as_view(http_method_names=['get', 'post']), - name='intervention-amendments-add'), - url(r'^interventions/amendments/(?P\d+)/$', - view=InterventionAmendmentDeleteView.as_view(http_method_names=['delete', ]), - name='intervention-amendments-del'), - url(r'^interventions/locations/$', - view=InterventionLocationListAPIView.as_view(http_method_names=['get', ]), - name='intervention-locations-list'), - url(r'^interventions/map/$', - view=InterventionListMapView.as_view(http_method_names=['get', ]), - name='intervention-map'), - url(r'^interventions/partnership-dash/$', - view=InterventionPartnershipDashView.as_view(http_method_names=['get', ]), - name='interventions-partnership-dash'), - - url(r'^interventions/(?P\d+)/reporting-periods/$', - view=InterventionReportingPeriodListCreateView.as_view(http_method_names=['get', 'post']), - name='intervention-reporting-periods-list'), - url(r'^interventions/reporting-periods/(?P\d+)/$', - view=InterventionReportingPeriodDetailView.as_view(http_method_names=['get', 'patch', 'delete']), - name='intervention-reporting-periods-detail'), - url( + re_path(r'^partners/hact/$', + view=PartnerOrganizationHactAPIView.as_view(http_method_names=['get', ]), + name='partner-hact'), + re_path(r'^partners/hact/simple/$', + view=PartnerOrganizationSimpleHactAPIView.as_view(http_method_names=['get', ]), + name='partner-hact-simple'), + re_path(r'^partners/dashboard/$', + view=PartnerOrganizationDashboardAPIView.as_view(http_method_names=['get', ]), + name='partner-dashboard'), + re_path(r'^partners/engagements/$', + view=PlannedEngagementAPIView.as_view(http_method_names=['get', ]), + name='partner-engagements'), + re_path(r'^partners/(?P\d+)/$', + view=PartnerOrganizationDetailAPIView.as_view(http_method_names=['get', 'patch']), + name='partner-detail'), + re_path(r'^partners/delete/(?P\d+)/$', + view=PartnerOrganizationDeleteView.as_view(http_method_names=['delete']), + name='partner-delete'), + re_path(r'^partners/assessments/$', + view=PartnerOrganizationAssessmentListCreateView.as_view(http_method_names=['get', 'post']), + name='partner-assessment'), + re_path(r'^partners/assessments/(?P\d+)/$', + view=PartnerOrganizationAssessmentUpdateDeleteView.as_view(http_method_names=['delete', 'patch']), + name='partner-assessment-detail'), + re_path(r'^partners/add/$', view=PartnerOrganizationAddView.as_view(http_method_names=['post']), name='partner-add'), + + re_path(r'^partners/(?P\d+)/staff-members/$', + view=PartnerStaffMemberListAPIVIew.as_view(http_method_names=['get']), + name='partner-staff-members-list'), + + re_path(r'^interventions/$', + view=InterventionListAPIView.as_view(http_method_names=['get', 'post']), + name='intervention-list'), + + re_path(r'^interventions/applied-indicators/$', + view=InterventionWithAppliedIndicatorsView.as_view(http_method_names=['get', ]), + name='intervention-applied-indicators-list'), + + re_path(r'^interventions/result-links/(?P\d+)/lower-results/$', + view=InterventionLowerResultListCreateView.as_view(http_method_names=['get', 'post']), + name='intervention-lower-results-list'), + + re_path(r'^interventions/(?P\d+)/result-links/$', + view=InterventionResultLinkListCreateView.as_view(http_method_names=['get', 'post']), + name='intervention-result-links-list'), + + re_path(r'^interventions/result-links/(?P\d+)/$', + view=InterventionResultLinkUpdateView.as_view(http_method_names=['get', 'patch', 'delete']), + name='intervention-result-links-update'), + + + re_path(r'^interventions/lower-results/(?P\d+)/$', + view=InterventionLowerResultUpdateView.as_view(http_method_names=['get', 'patch', 'delete']), + name='intervention-lower-results-update'), + + re_path(r'^interventions/lower-results/(?P\d+)/indicators/$', + view=InterventionIndicatorsListView.as_view(http_method_names=['get', 'post']), + name='intervention-indicators-list'), + + re_path(r'^interventions/applied-indicators/(?P\d+)/$', + view=InterventionIndicatorsUpdateView.as_view(http_method_names=['get', 'patch', 'delete']), + name='intervention-indicators-update'), + + re_path(r'^interventions/dash/$', + view=InterventionListDashView.as_view(http_method_names=['get', 'post']), + name='intervention-list-dash'), + + re_path(r'^interventions/(?P\d+)/$', + view=InterventionDetailAPIView.as_view(http_method_names=['get', 'patch']), + name='intervention-detail'), + re_path(r'^interventions/delete/(?P\d+)/$', + view=InterventionDeleteView.as_view(http_method_names=['delete']), + name='intervention-delete'), + + re_path(r'^interventions/(?P\d+)/attachments/$', + view=InterventionAttachmentListCreateView.as_view(http_method_names=['get', 'post']), + name='intervention-attachment-list'), + + re_path(r'^interventions/attachments/(?P\d+)/$', + view=InterventionAttachmentUpdateDeleteView.as_view(http_method_names=['delete', 'patch']), + name='intervention-attachments-update'), + + re_path(r'^interventions/indicators/$', + view=InterventionIndicatorListAPIView.as_view(http_method_names=['get', ]), + name='intervention-indicators'), + re_path(r'^interventions/results/$', + view=InterventionResultListAPIView.as_view(http_method_names=['get', ]), + name='intervention-results'), + re_path(r'^interventions/amendments/$', + view=InterventionAmendmentListAPIView.as_view(http_method_names=['get']), + name='intervention-amendments'), + re_path(r'^interventions/(?P\d+)/amendments/$', + view=InterventionAmendmentListAPIView.as_view(http_method_names=['get', 'post']), + name='intervention-amendments-add'), + re_path(r'^interventions/amendments/(?P\d+)/$', + view=InterventionAmendmentDeleteView.as_view(http_method_names=['delete', ]), + name='intervention-amendments-del'), + re_path(r'^interventions/locations/$', + view=InterventionLocationListAPIView.as_view(http_method_names=['get', ]), + name='intervention-locations-list'), + re_path(r'^interventions/map/$', + view=InterventionListMapView.as_view(http_method_names=['get', ]), + name='intervention-map'), + re_path(r'^interventions/partnership-dash/$', + view=InterventionPartnershipDashView.as_view(http_method_names=['get', ]), + name='interventions-partnership-dash'), + + re_path(r'^interventions/(?P\d+)/reporting-periods/$', + view=InterventionReportingPeriodListCreateView.as_view(http_method_names=['get', 'post']), + name='intervention-reporting-periods-list'), + re_path(r'^interventions/reporting-periods/(?P\d+)/$', + view=InterventionReportingPeriodDetailView.as_view(http_method_names=['get', 'patch', 'delete']), + name='intervention-reporting-periods-detail'), + re_path( r'^interventions/(?P\d+)/reporting-requirements/(?P\w+)/$', view=InterventionReportingRequirementView.as_view( http_method_names=['get', 'post', 'patch', 'delete'] ), name='intervention-reporting-requirements' ), - url( + re_path( r'interventions/(?P\d+)/output_cp_indicators/(?P\d+)/$', view=InterventionRamIndicatorsView.as_view(http_method_names=['get']), name="interventions-output-cp-indicators", ), - url( + re_path( r'interventions/(?P\d+)/planned-visits/(?P\d+)/$', view=InterventionPlannedVisitsDeleteView.as_view(http_method_names=['delete']), name="interventions-planned-visits-delete", ), - url(r'^dropdowns/static/$', - view=PMPStaticDropdownsListAPIView.as_view(http_method_names=['get']), - name='dropdown-static-list'), - url(r'^dropdowns/pmp/$', - view=PMPDropdownsListApiView.as_view(http_method_names=['get']), name='dropdown-pmp-list'), + re_path(r'^dropdowns/static/$', + view=PMPStaticDropdownsListAPIView.as_view(http_method_names=['get']), + name='dropdown-static-list'), + re_path(r'^dropdowns/pmp/$', + view=PMPDropdownsListApiView.as_view(http_method_names=['get']), name='dropdown-pmp-list'), ) urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'csv']) diff --git a/src/etools/applications/psea/__init__.py b/src/etools/applications/psea/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/psea/__init__.py +++ b/src/etools/applications/psea/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/publics/urls.py b/src/etools/applications/publics/urls.py index cd0e76c546..995d78e225 100644 --- a/src/etools/applications/publics/urls.py +++ b/src/etools/applications/publics/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from etools.applications.publics.views import ( AirlinesView, @@ -11,21 +11,21 @@ app_name = 'publics' urlpatterns = ( - url(r'^static_data/$', StaticDataView.as_view({'get': 'list'}), name='static'), - url(r'^static_data/missing/$', StaticDataView.as_view({'get': 'missing'}), name='missing_static'), + re_path(r'^static_data/$', StaticDataView.as_view({'get': 'list'}), name='static'), + re_path(r'^static_data/missing/$', StaticDataView.as_view({'get': 'missing'}), name='missing_static'), - url(r'^currencies/$', CurrenciesView.as_view({'get': 'list'}), name='currencies'), - url(r'^currencies/missing/$', CurrenciesView.as_view({'get': 'missing'}), name='missing_currencies'), + re_path(r'^currencies/$', CurrenciesView.as_view({'get': 'list'}), name='currencies'), + re_path(r'^currencies/missing/$', CurrenciesView.as_view({'get': 'missing'}), name='missing_currencies'), - url(r'^dsa_regions/$', DSARegionsView.as_view({'get': 'list'}), name='dsa_regions'), - url(r'^dsa_regions/missing/$', DSARegionsView.as_view({'get': 'missing'}), name='missing_dsa_regions'), + re_path(r'^dsa_regions/$', DSARegionsView.as_view({'get': 'list'}), name='dsa_regions'), + re_path(r'^dsa_regions/missing/$', DSARegionsView.as_view({'get': 'missing'}), name='missing_dsa_regions'), - url(r'^business_areas/$', BusinessAreasView.as_view({'get': 'list'}), name='business_areas'), - url(r'^business_areas/missing/$', BusinessAreasView.as_view({'get': 'missing'}), name='missing_business_areas'), + re_path(r'^business_areas/$', BusinessAreasView.as_view({'get': 'list'}), name='business_areas'), + re_path(r'^business_areas/missing/$', BusinessAreasView.as_view({'get': 'missing'}), name='missing_business_areas'), - url(r'^expense_types/$', ExpenseTypesView.as_view({'get': 'list'}), name='expense_types'), - url(r'^expense_types/missing/$', ExpenseTypesView.as_view({'get': 'missing'}), name='missing_expense_types'), + re_path(r'^expense_types/$', ExpenseTypesView.as_view({'get': 'list'}), name='expense_types'), + re_path(r'^expense_types/missing/$', ExpenseTypesView.as_view({'get': 'missing'}), name='missing_expense_types'), - url(r'^airlines/$', AirlinesView.as_view({'get': 'list'}), name='airlines'), - url(r'^airlines/missing/$', AirlinesView.as_view({'get': 'missing'}), name='missing_airlines'), + re_path(r'^airlines/$', AirlinesView.as_view({'get': 'list'}), name='airlines'), + re_path(r'^airlines/missing/$', AirlinesView.as_view({'get': 'missing'}), name='missing_airlines'), ) diff --git a/src/etools/applications/reports/__init__.py b/src/etools/applications/reports/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/reports/__init__.py +++ b/src/etools/applications/reports/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/reports/urls_v2.py b/src/etools/applications/reports/urls_v2.py index 889ace9787..a58ae03af8 100644 --- a/src/etools/applications/reports/urls_v2.py +++ b/src/etools/applications/reports/urls_v2.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework import routers @@ -24,48 +24,48 @@ app_name = 'reports' urlpatterns = ( - url(r'^results/$', view=OutputListAPIView.as_view(), name='report-result-list'), - url(r'^applied-indicators/$', - view=AppliedIndicatorListAPIView.as_view(http_method_names=['get']), - name='applied-indicator'), - url(r'^applied-indicators/intervention/$', - view=AppliedIndicatorLocationExportView.as_view(http_method_names=['get']), - name='intervention-applied-indicator'), - url(r'^clusters/$', - view=ClusterListAPIView.as_view(http_method_names=['get']), - name='cluster'), - url(r'^lower_results/$', - view=LowerResultsListAPIView.as_view(http_method_names=['get']), - name='lower-results'), - url(r'^lower_results/(?P\d+)/$', - view=LowerResultsDeleteView.as_view(http_method_names=['delete']), - name='lower-results-del'), - url(r'^results/(?P\d+)/$', view=OutputDetailAPIView.as_view(), name='report-result-detail'), - url(r'^countryprogramme/$', view=CountryProgrammeListView.as_view(), - name='country-programme-list'), - url(r'^countryprogramme/(?P\d+)/$', - view=CountryProgrammeRetrieveView.as_view(http_method_names=['get']), name='country-programme-retrieve'), - url(r'^results/(?P\d+)/indicators/$', - view=ResultIndicatorListAPIView.as_view(http_method_names=['get']), - name='result-indicator-list'), - url(r'disaggregations/$', view=DisaggregationListCreateView.as_view(), - name='disaggregation-list-create'), - url(r'disaggregations/(?P\d+)/$', view=DisaggregationRetrieveUpdateView.as_view(), - name='disaggregation-retrieve-update'), - url( + re_path(r'^results/$', view=OutputListAPIView.as_view(), name='report-result-list'), + re_path(r'^applied-indicators/$', + view=AppliedIndicatorListAPIView.as_view(http_method_names=['get']), + name='applied-indicator'), + re_path(r'^applied-indicators/intervention/$', + view=AppliedIndicatorLocationExportView.as_view(http_method_names=['get']), + name='intervention-applied-indicator'), + re_path(r'^clusters/$', + view=ClusterListAPIView.as_view(http_method_names=['get']), + name='cluster'), + re_path(r'^lower_results/$', + view=LowerResultsListAPIView.as_view(http_method_names=['get']), + name='lower-results'), + re_path(r'^lower_results/(?P\d+)/$', + view=LowerResultsDeleteView.as_view(http_method_names=['delete']), + name='lower-results-del'), + re_path(r'^results/(?P\d+)/$', view=OutputDetailAPIView.as_view(), name='report-result-detail'), + re_path(r'^countryprogramme/$', view=CountryProgrammeListView.as_view(), + name='country-programme-list'), + re_path(r'^countryprogramme/(?P\d+)/$', + view=CountryProgrammeRetrieveView.as_view(http_method_names=['get']), name='country-programme-retrieve'), + re_path(r'^results/(?P\d+)/indicators/$', + view=ResultIndicatorListAPIView.as_view(http_method_names=['get']), + name='result-indicator-list'), + re_path(r'disaggregations/$', view=DisaggregationListCreateView.as_view(), + name='disaggregation-list-create'), + re_path(r'disaggregations/(?P\d+)/$', view=DisaggregationRetrieveUpdateView.as_view(), + name='disaggregation-retrieve-update'), + re_path( r'interventions/(?P\d+)/special-reporting-requirements/$', view=SpecialReportingRequirementListCreateView.as_view(), name="interventions-special-reporting-requirements", ), - url( + re_path( r'interventions/special-reporting-requirements/(?P\d+)/$', view=SpecialReportingRequirementRetrieveUpdateDestroyView.as_view(), name="interventions-special-reporting-requirements-update", ), - url( + re_path( r'interventions/results/(?P\d+)/$', view=ResultFrameworkView.as_view(), name="interventions-results-framework", ), - url(r'^', include(api.urls)) + re_path(r'^', include(api.urls)) ) diff --git a/src/etools/applications/t2f/urls.py b/src/etools/applications/t2f/urls.py index 8c9ac9904d..4967693c80 100644 --- a/src/etools/applications/t2f/urls.py +++ b/src/etools/applications/t2f/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from etools.applications.t2f.models import Travel from etools.applications.t2f.views.dashboard import TravelDashboardViewSet @@ -34,35 +34,35 @@ details_state_changes_pattern = r"^(?P{})/$".format("|".join(Travel.TRANSACTIONS)) travel_details_patterns = (( - url(r'^$', travel_details, name='index'), - url(r'^attachments/$', travel_attachments, name='attachments'), - url(r'^attachments/(?P[0-9]+)/$', travel_attachment_details, name='attachment_details'), - url(details_state_changes_pattern, travel_details_state_change, name='state_change'), - url(r'duplicate_travel/$', clone_travel_for_secondary_traveler, name='clone_for_secondary_traveler'), + re_path(r'^$', travel_details, name='index'), + re_path(r'^attachments/$', travel_attachments, name='attachments'), + re_path(r'^attachments/(?P[0-9]+)/$', travel_attachment_details, name='attachment_details'), + re_path(details_state_changes_pattern, travel_details_state_change, name='state_change'), + re_path(r'duplicate_travel/$', clone_travel_for_secondary_traveler, name='clone_for_secondary_traveler'), ), 'details') travel_list_patterns = (( - url(r'^$', travel_list, name='index'), - url(r'^(?Psave_and_submit|mark_as_completed)/$', travel_list_state_change, name='state_change'), - url(r'^export/$', TravelActivityExport.as_view(), name='activity_export'), - url(r'^travel-admin-export/$', TravelAdminExport.as_view(), name='travel_admin_export'), - url(r'^activities/partnership/(?P[0-9]+)/', - TravelActivityPerInterventionViewSet.as_view({'get': 'list'}), name='activities-intervention'), - url(r'^activities/(?P[0-9]+)/', TravelActivityViewSet.as_view({'get': 'list'}), - name='activities'), - url(r'^dashboard', travel_dashboard_list, name='dashboard'), + re_path(r'^$', travel_list, name='index'), + re_path(r'^(?Psave_and_submit|mark_as_completed)/$', travel_list_state_change, name='state_change'), + re_path(r'^export/$', TravelActivityExport.as_view(), name='activity_export'), + re_path(r'^travel-admin-export/$', TravelAdminExport.as_view(), name='travel_admin_export'), + re_path(r'^activities/partnership/(?P[0-9]+)/', + TravelActivityPerInterventionViewSet.as_view({'get': 'list'}), name='activities-intervention'), + re_path(r'^activities/(?P[0-9]+)/', TravelActivityViewSet.as_view({'get': 'list'}), + name='activities'), + re_path(r'^dashboard', travel_dashboard_list, name='dashboard'), ), 'list') travel_patterns = (( - url(r'^', include(travel_list_patterns)), - url(r'^(?P[0-9]+)/', include(travel_details_patterns)), + re_path(r'^', include(travel_list_patterns)), + re_path(r'^(?P[0-9]+)/', include(travel_details_patterns)), ), 'travels') urlpatterns = (( - url(r'^travels/', include(travel_patterns)), - url(r'^static_data/$', StaticDataView.as_view(), name='static_data'), - url(r'^permission_matrix/$', PermissionMatrixView.as_view(), name='permission_matrix'), + re_path(r'^travels/', include(travel_patterns)), + re_path(r'^static_data/$', StaticDataView.as_view(), name='static_data'), + re_path(r'^permission_matrix/$', PermissionMatrixView.as_view(), name='permission_matrix'), ), 't2f') diff --git a/src/etools/applications/tpm/__init__.py b/src/etools/applications/tpm/__init__.py index 8084bfba87..e69de29bb2 100644 --- a/src/etools/applications/tpm/__init__.py +++ b/src/etools/applications/tpm/__init__.py @@ -1 +0,0 @@ -default_app_config = __name__ + '.apps.AppConfig' diff --git a/src/etools/applications/tpm/models.py b/src/etools/applications/tpm/models.py index 8d11344c3d..c1a042ad84 100644 --- a/src/etools/applications/tpm/models.py +++ b/src/etools/applications/tpm/models.py @@ -3,7 +3,7 @@ from django.conf import settings from django.db import connection, models from django.utils import timezone -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ @@ -446,10 +446,10 @@ def pv_applicable(self): def get_mail_context(self, user=None, include_visit=True): context = { - 'locations': ', '.join(map(force_text, self.locations.all())), + 'locations': ', '.join(map(force_str, self.locations.all())), 'intervention': self.intervention.title if self.intervention else '-', - 'cp_output': force_text(self.cp_output) if self.cp_output else '-', - 'section': force_text(self.section) if self.section else '-', + 'cp_output': force_str(self.cp_output) if self.cp_output else '-', + 'section': force_str(self.section) if self.section else '-', 'partner': self.partner.name if self.partner else '-', } if include_visit: diff --git a/src/etools/applications/tpm/urls.py b/src/etools/applications/tpm/urls.py index ae36e24200..020c6c17c8 100644 --- a/src/etools/applications/tpm/urls.py +++ b/src/etools/applications/tpm/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework_nested import routers from unicef_restlib.routers import NestedComplexRouter @@ -46,18 +46,18 @@ app_name = 'tpm' urlpatterns = [ - url(r'^', include(tpm_staffmember_api.urls)), - url(r'^', include(partner_attachments_api.urls)), - url(r'^', include(tpm_partners_api.urls)), - url(r'^', include(tpm_action_points_api.urls)), - url(r'^', include(visit_attachments_api.urls)), - url(r'^', include(tpm_visits_api.urls)), - url( + re_path(r'^', include(tpm_staffmember_api.urls)), + re_path(r'^', include(partner_attachments_api.urls)), + re_path(r'^', include(tpm_partners_api.urls)), + re_path(r'^', include(tpm_action_points_api.urls)), + re_path(r'^', include(visit_attachments_api.urls)), + re_path(r'^', include(tpm_visits_api.urls)), + re_path( r'^visits/activities/(?P\d+)/links', view=ActivityAttachmentLinksView.as_view(), name='activity-links' ), - url( + re_path( r'^visits/(?P\d+)/links', view=VisitAttachmentLinksView.as_view(), name='visit-links' diff --git a/src/etools/applications/users/serializers.py b/src/etools/applications/users/serializers.py index 4aecf6aea6..b94537d098 100644 --- a/src/etools/applications/users/serializers.py +++ b/src/etools/applications/users/serializers.py @@ -1,5 +1,5 @@ from django.contrib.auth import get_user_model -from django.utils.encoding import force_text +from django.utils.encoding import force_str from rest_framework import serializers @@ -123,7 +123,7 @@ def create(self, validated_data): group = Group.objects.create(**validated_data) except Exception as ex: - raise serializers.ValidationError({'group': force_text(ex)}) + raise serializers.ValidationError({'group': force_str(ex)}) return group @@ -210,7 +210,7 @@ def create(self, validated_data): user.profile.save() except Exception as ex: - raise serializers.ValidationError({'user': force_text(ex)}) + raise serializers.ValidationError({'user': force_str(ex)}) return user diff --git a/src/etools/applications/users/urls.py b/src/etools/applications/users/urls.py index 080271e52e..e8cce4c002 100644 --- a/src/etools/applications/users/urls.py +++ b/src/etools/applications/users/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from etools.applications.users.views import ( ChangeUserCountryView, @@ -11,9 +11,9 @@ app_name = 'users' urlpatterns = ( # api - url(r'^api/changecountry/$', ChangeUserCountryView.as_view(), name="country-change"), - url(r'^api/user_management/$', ChangeUserRoleView.as_view(http_method_names=['post']), name="user-change"), - url(r'^api/$', StaffUsersView.as_view()), - url(r'^api/(?P\d+)/$', UsersDetailAPIView.as_view(http_method_names=['get']), name="user-detail"), - url(r'^myprofile/$', MyProfileAPIView.as_view(), name="myprofile-detail"), + re_path(r'^api/changecountry/$', ChangeUserCountryView.as_view(), name="country-change"), + re_path(r'^api/user_management/$', ChangeUserRoleView.as_view(http_method_names=['post']), name="user-change"), + re_path(r'^api/$', StaffUsersView.as_view()), + re_path(r'^api/(?P\d+)/$', UsersDetailAPIView.as_view(http_method_names=['get']), name="user-detail"), + re_path(r'^myprofile/$', MyProfileAPIView.as_view(), name="myprofile-detail"), ) diff --git a/src/etools/applications/users/urls_v2.py b/src/etools/applications/users/urls_v2.py index 6e5c761a77..ee20451236 100644 --- a/src/etools/applications/users/urls_v2.py +++ b/src/etools/applications/users/urls_v2.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from etools.applications.users.views_v2 import ( ChangeUserCountryView, @@ -11,10 +11,10 @@ app_name = 'users' urlpatterns = ( - url(r'^changecountry/$', ChangeUserCountryView.as_view(http_method_names=['post']), name="country-change"), - url(r'^$', StaffUsersView.as_view()), - url(r'^(?P\d)/$', UsersDetailAPIView.as_view(http_method_names=['get']), name="user-detail"), - url(r'^myprofile/$', MyProfileAPIView.as_view(), name="myprofile-detail"), - url(r'^country/$', CountryView.as_view(http_method_names=['get']), name="country-detail"), - url(r'^workspaces', CountriesViewSet.as_view(http_method_names=['get']), name="list-workspaces"), + re_path(r'^changecountry/$', ChangeUserCountryView.as_view(http_method_names=['post']), name="country-change"), + re_path(r'^$', StaffUsersView.as_view()), + re_path(r'^(?P\d)/$', UsersDetailAPIView.as_view(http_method_names=['get']), name="user-detail"), + re_path(r'^myprofile/$', MyProfileAPIView.as_view(), name="myprofile-detail"), + re_path(r'^country/$', CountryView.as_view(http_method_names=['get']), name="country-detail"), + re_path(r'^workspaces', CountriesViewSet.as_view(http_method_names=['get']), name="list-workspaces"), ) diff --git a/src/etools/applications/users/urls_v3.py b/src/etools/applications/users/urls_v3.py index 0067402d05..064ec9efa1 100644 --- a/src/etools/applications/users/urls_v3.py +++ b/src/etools/applications/users/urls_v3.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from rest_framework_nested import routers @@ -17,11 +17,11 @@ app_name = 'users' urlpatterns = ( - url(r'^profile/$', MyProfileAPIView.as_view(http_method_names=['get', 'patch']), name="myprofile-detail"), - url(r'^changecountry/$', ChangeUserCountryView.as_view(), name="country-change"), - url(r'^country/$', CountryView.as_view(http_method_names=['get']), name="country-detail"), - url(r'^(?P[0-9]+)/$', UsersDetailAPIView.as_view(http_method_names=['get']), name="user-detail"), - url(r'^AD/(?P.*)$', ADUserAPIView.as_view(http_method_names=['get', ]), name="ad-user-api-view"), - url(r'^', include(root_api.urls)), - url(r'^$', UsersListAPIView.as_view(), name="users-list"), + re_path(r'^profile/$', MyProfileAPIView.as_view(http_method_names=['get', 'patch']), name="myprofile-detail"), + re_path(r'^changecountry/$', ChangeUserCountryView.as_view(), name="country-change"), + re_path(r'^country/$', CountryView.as_view(http_method_names=['get']), name="country-detail"), + re_path(r'^(?P[0-9]+)/$', UsersDetailAPIView.as_view(http_method_names=['get']), name="user-detail"), + re_path(r'^AD/(?P.*)$', ADUserAPIView.as_view(http_method_names=['get', ]), name="ad-user-api-view"), + re_path(r'^', include(root_api.urls)), + re_path(r'^$', UsersListAPIView.as_view(), name="users-list"), ) diff --git a/src/etools/config/settings/base.py b/src/etools/config/settings/base.py index 6f35f5f429..ba457ce10e 100644 --- a/src/etools/config/settings/base.py +++ b/src/etools/config/settings/base.py @@ -502,7 +502,7 @@ def before_send(event, hint): SOCIAL_AUTH_URL_NAMESPACE = 'social' SOCIAL_AUTH_SANITIZE_REDIRECTS = False -SOCIAL_AUTH_POSTGRES_JSONFIELD = True +SOCIAL_AUTH_JSONFIELD_ENABLED = True POLICY = os.getenv('AZURE_B2C_POLICY_NAME', "b2c_1A_UNICEF_PARTNERS_signup_signin") TENANT_ID = os.getenv('AZURE_B2C_TENANT', 'unicefpartners') diff --git a/src/etools/config/urls.py b/src/etools/config/urls.py index 57345ce86b..e92a3f5bc0 100644 --- a/src/etools/config/urls.py +++ b/src/etools/config/urls.py @@ -1,6 +1,6 @@ from django.conf import settings -from django.conf.urls import include, url from django.contrib import admin +from django.urls import include, re_path from django.views.generic import TemplateView from rest_framework_nested import routers @@ -63,61 +63,61 @@ urlpatterns = [ # Used for admin and dashboard pages in django - url(r'^$', ModuleRedirectView.as_view(), name='dashboard'), - url(r'^login/$', MainView.as_view(), name='main'), - url(r'^logout/$', logout_view, name='logout'), + re_path(r'^$', ModuleRedirectView.as_view(), name='dashboard'), + re_path(r'^login/$', MainView.as_view(), name='main'), + re_path(r'^logout/$', logout_view, name='logout'), - url(r'^api/static_data/$', StaticDataView.as_view({'get': 'list'}), name='public_static'), + re_path(r'^api/static_data/$', StaticDataView.as_view({'get': 'list'}), name='public_static'), # *************** API version 1 ******************** - url(r'^locations/', include('unicef_locations.urls')), - url(r'^locations/cartodbtables/$', CartoDBTablesView.as_view(), name='cartodbtables'), - url(r'^locations/autocomplete/$', LocationQuerySetView.as_view(), name='locations_autocomplete'), - url(r'^api/v1/field-monitoring/', include('etools.applications.field_monitoring.urls')), + re_path(r'^locations/', include('unicef_locations.urls')), + re_path(r'^locations/cartodbtables/$', CartoDBTablesView.as_view(), name='cartodbtables'), + re_path(r'^locations/autocomplete/$', LocationQuerySetView.as_view(), name='locations_autocomplete'), + re_path(r'^api/v1/field-monitoring/', include('etools.applications.field_monitoring.urls')), # GIS API urls - url(r'^api/management/gis/', include('etools.applications.management.urls_gis')), - url(r'^users/', include('etools.applications.users.urls')), - url(r'^api/management/', include(management_urls)), - url(r'^api/', include(api.urls)), - url(r'^api/', include(publics_patterns)), + re_path(r'^api/management/gis/', include('etools.applications.management.urls_gis')), + re_path(r'^users/', include('etools.applications.users.urls')), + re_path(r'^api/management/', include(management_urls)), + re_path(r'^api/', include(api.urls)), + re_path(r'^api/', include(publics_patterns)), # *************** API version 2 ****************** - url(r'^api/locations/pcode/(?P\w+)/$', - LocationsViewSet.as_view({'get': 'retrieve'}), - name='locations_detail_pcode'), - url(r'^api/t2f/', include(t2f_patterns)), - url(r'^api/tpm/', include('etools.applications.tpm.urls')), - url(r'^api/audit/', include('etools.applications.audit.urls')), - url(r'^api/action-points/', include('etools.applications.action_points.urls')), - url(r'^api/psea/', include('etools.applications.psea.urls')), - url(r'^api/v2/reports/', include('etools.applications.reports.urls_v2')), - url(r'^api/v2/', include('etools.applications.partners.urls_v2', namespace='partners_api')), - url(r'^api/prp/v1/', include('etools.applications.partners.prp_urls', namespace='prp_api_v1')), - url(r'^api/v2/hact/', include('etools.applications.hact.urls')), - url(r'^api/v2/users/', include('etools.applications.users.urls_v2', namespace='users_v2')), - url(r'^api/v2/workspaces/', CountriesViewSet.as_view(http_method_names=['get']), name="list-workspaces"), - url(r'^api/v2/funds/', include('etools.applications.funds.urls')), - url(r'^api/v2/activity/', include('unicef_snapshot.urls')), - url(r'^api/v2/environment/', include('etools.applications.environment.urls_v2')), - url(r'^api/v2/attachments/', include('unicef_attachments.urls')), + re_path(r'^api/locations/pcode/(?P\w+)/$', + LocationsViewSet.as_view({'get': 'retrieve'}), + name='locations_detail_pcode'), + re_path(r'^api/t2f/', include(t2f_patterns)), + re_path(r'^api/tpm/', include('etools.applications.tpm.urls')), + re_path(r'^api/audit/', include('etools.applications.audit.urls')), + re_path(r'^api/action-points/', include('etools.applications.action_points.urls')), + re_path(r'^api/psea/', include('etools.applications.psea.urls')), + re_path(r'^api/v2/reports/', include('etools.applications.reports.urls_v2')), + re_path(r'^api/v2/', include('etools.applications.partners.urls_v2', namespace='partners_api')), + re_path(r'^api/prp/v1/', include('etools.applications.partners.prp_urls', namespace='prp_api_v1')), + re_path(r'^api/v2/hact/', include('etools.applications.hact.urls')), + re_path(r'^api/v2/users/', include('etools.applications.users.urls_v2', namespace='users_v2')), + re_path(r'^api/v2/workspaces/', CountriesViewSet.as_view(http_method_names=['get']), name="list-workspaces"), + re_path(r'^api/v2/funds/', include('etools.applications.funds.urls')), + re_path(r'^api/v2/activity/', include('unicef_snapshot.urls')), + re_path(r'^api/v2/environment/', include('etools.applications.environment.urls_v2')), + re_path(r'^api/v2/attachments/', include('unicef_attachments.urls')), # *************** API version 3 ****************** - url(r'^api/v3/users/', include('etools.applications.users.urls_v3', namespace='users_v3')), + re_path(r'^api/v3/users/', include('etools.applications.users.urls_v3', namespace='users_v3')), - url(r'^api/docs/', schema_view), - url(r'^api/schema/coreapi', schema_view_json_coreapi), - url(r'^api/schema/openapi', schema_view_json_openapi), - url(r'^admin/', admin.site.urls), + re_path(r'^api/docs/', schema_view), + re_path(r'^api/schema/coreapi', schema_view_json_coreapi), + re_path(r'^api/schema/openapi', schema_view_json_openapi), + re_path(r'^admin/', admin.site.urls), - url(r'^workspace_inactive/$', TemplateView.as_view(template_name='removed_workspace.html'), - name='workspace-inactive'), + re_path(r'^workspace_inactive/$', TemplateView.as_view(template_name='removed_workspace.html'), + name='workspace-inactive'), - url(r'^api/jwt/get/$', IssueJWTRedirectView.as_view(), name='issue JWT'), + re_path(r'^api/jwt/get/$', IssueJWTRedirectView.as_view(), name='issue JWT'), - url('^social/', include('social_django.urls', namespace='social')), - url('^monitoring/', include('etools.libraries.monitoring.urls')), + re_path('^social/', include('social_django.urls', namespace='social')), + re_path('^monitoring/', include('etools.libraries.monitoring.urls')), ] @@ -125,5 +125,5 @@ import debug_toolbar urlpatterns += [ - url(r'^__debug__/', include(debug_toolbar.urls)), + re_path(r'^__debug__/', include(debug_toolbar.urls)), ] diff --git a/src/etools/libraries/azure_graph_api/tasks.py b/src/etools/libraries/azure_graph_api/tasks.py index b9218492ef..5d7cb8731b 100644 --- a/src/etools/libraries/azure_graph_api/tasks.py +++ b/src/etools/libraries/azure_graph_api/tasks.py @@ -1,6 +1,6 @@ from django.conf import settings from django.core.cache import cache -from django.utils.encoding import force_text +from django.utils.encoding import force_str import requests from celery.utils.log import get_task_logger @@ -41,8 +41,8 @@ def sync_all_users(): ) status, _ = azure_sync_users(url) except Exception as e: - log.exception_message = force_text(e) - logger.exception(force_text(e)) + log.exception_message = force_str(e) + logger.exception(force_str(e)) raise VisionException(*e.args) else: log.total_records = status['processed'] + status['skipped'] @@ -71,8 +71,8 @@ def sync_delta_users(): cache.set(AZURE_GRAPH_API_USER_CACHE_KEY, delta_link) except Exception as e: - log.exception_message = force_text(e) - logger.exception(force_text(e)) + log.exception_message = force_str(e) + logger.exception(force_str(e)) raise VisionException(*e.args) else: log.total_records = status['processed'] + status['skipped'] diff --git a/src/etools/libraries/locations/urls.py b/src/etools/libraries/locations/urls.py index e0bd2fbb7a..ec16a5608f 100644 --- a/src/etools/libraries/locations/urls.py +++ b/src/etools/libraries/locations/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from rest_framework import routers @@ -17,6 +17,6 @@ api.register(r'locations-types', LocationTypesViewSet, basename='locationtypes') urlpatterns = [ - url(r'^cartodbtables/$', CartoDBTablesView.as_view(), name='cartodbtables'), - url(r'^autocomplete/$', LocationQuerySetView.as_view(), name='locations_autocomplete'), + re_path(r'^cartodbtables/$', CartoDBTablesView.as_view(), name='cartodbtables'), + re_path(r'^autocomplete/$', LocationQuerySetView.as_view(), name='locations_autocomplete'), ] diff --git a/src/etools/libraries/monitoring/urls.py b/src/etools/libraries/monitoring/urls.py index 0ce5704c18..3cdc6296cf 100644 --- a/src/etools/libraries/monitoring/urls.py +++ b/src/etools/libraries/monitoring/urls.py @@ -1,10 +1,10 @@ -from django.conf.urls import url +from django.urls import re_path from etools.libraries.monitoring.views import AppAliveView, AppReadyView app_name = 'monitoring' urlpatterns = ( - url(r'^app_alive/$', AppAliveView.as_view(), name="app_alive"), - url(r'^app_ready/$', AppReadyView.as_view(), name="app_ready"), + re_path(r'^app_alive/$', AppAliveView.as_view(), name="app_alive"), + re_path(r'^app_ready/$', AppReadyView.as_view(), name="app_ready"), ) From 483e3cac364eb772bdd253bb8d8ac767a1bc9b58 Mon Sep 17 00:00:00 2001 From: Domenico Date: Wed, 5 Jan 2022 16:41:03 -0600 Subject: [PATCH 13/39] 2022 fixes --- src/etools/applications/psea/tests/test_models.py | 6 +++--- src/etools/applications/reports/synchronizers.py | 1 - src/etools/applications/reports/tests/test_synchronizers.py | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/etools/applications/psea/tests/test_models.py b/src/etools/applications/psea/tests/test_models.py index b869ea606e..d4dc63c8c7 100644 --- a/src/etools/applications/psea/tests/test_models.py +++ b/src/etools/applications/psea/tests/test_models.py @@ -182,7 +182,7 @@ def test_user_belongs_staff(self): def test_get_mail_context(self): user = UserFactory() - assessment = AssessmentFactory(reference_number='TST/2021PSEA') + assessment = AssessmentFactory(reference_number='TST/{}PSEA'.format(timezone.now().year)) AssessorFactory(assessment=assessment) self.assertEqual(assessment.get_mail_context(user), { "partner_name": assessment.partner.name, @@ -195,7 +195,7 @@ def test_get_mail_context(self): "assessor": str(assessment.assessor), 'assessment_ingo_reason': None, 'assessment_type': 'UNICEF Assessment 2020', - 'reference_number': 'TST/2021PSEA{}'.format(assessment.pk), + 'reference_number': 'TST/{}PSEA{}'.format(timezone.now().year, assessment.pk), }) def test_get_reference_number(self): @@ -248,7 +248,7 @@ def test_get_mail_context(self): "assessor": str(assessment.assessor), 'assessment_ingo_reason': None, 'assessment_type': 'UNICEF Assessment 2020', - 'reference_number': 'TST/2021PSEA{}'.format(assessment.pk), + 'reference_number': 'TST/{}PSEA{}'.format(timezone.now().year, assessment.pk), }) diff --git a/src/etools/applications/reports/synchronizers.py b/src/etools/applications/reports/synchronizers.py index e46ee725e5..774f961296 100644 --- a/src/etools/applications/reports/synchronizers.py +++ b/src/etools/applications/reports/synchronizers.py @@ -303,7 +303,6 @@ def _convert_records(self, records): for k in self.DATES: r[k] = datetime.datetime.strptime(r[k], INSIGHT_DATE_FORMAT).date() if r[k] else None r['HUMANITARIAN_TAG'] = r['HUMANITARIAN_TAG'] not in ['No', 'None', '0'] - return self._clean_records(records) def _save_records(self, records): diff --git a/src/etools/applications/reports/tests/test_synchronizers.py b/src/etools/applications/reports/tests/test_synchronizers.py index 0fe6b39679..9138e36e40 100644 --- a/src/etools/applications/reports/tests/test_synchronizers.py +++ b/src/etools/applications/reports/tests/test_synchronizers.py @@ -545,7 +545,7 @@ def test_convert_records(self): self.data["OUTCOME_AREA_CODE"] = "OC_CODE" self.data["OUTCOME_DESCRIPTION"] = "OC_NAME" self.data["OUTCOME_START_DATE"] = "20-Feb-13" - self.data["OUTCOME_END_DATE"] = "20-Feb-20" + self.data["OUTCOME_END_DATE"] = "20-Feb-{}".format(str(datetime.datetime.today().year)[2:]) self.data["OUTPUT_START_DATE"] = "29-Oct-44" self.data["OUTPUT_END_DATE"] = "29-Oct-44" self.data["ACTIVITY_START_DATE"] = "29-Oct-45" @@ -566,7 +566,7 @@ def test_convert_records(self): "wbs": "OC_WBS", "name": "OC_NAME", "from_date": datetime.date(2013, 2, 20), - "to_date": datetime.date(2020, 2, 20), + "to_date": datetime.date(datetime.datetime.today().year, 2, 20), }}, "outputs": {}, "activities": {} From 830a3dba20e6e531fcaaa7c35ef8f7155e7d532e Mon Sep 17 00:00:00 2001 From: blu Date: Mon, 27 Dec 2021 13:19:34 +0200 Subject: [PATCH 14/39] fix for sentry issues #ETOOLS-PROD-EH when deleting an agreement --- src/etools/applications/reports/models.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/etools/applications/reports/models.py b/src/etools/applications/reports/models.py index d2ed512776..0c1ee92c15 100644 --- a/src/etools/applications/reports/models.py +++ b/src/etools/applications/reports/models.py @@ -836,9 +836,12 @@ class ReportingRequirement(TimeStampedModel): class Meta: ordering = ("-end_date", ) + def get_report_type_display(self): + return dict(self.TYPE_CHOICES).get(self.report_type) + def __str__(self): return "{} ({}) {}".format( - self.get_report_type_display, + self.get_report_type_display(), self.report_type, self.due_date ) From b067d9ee8961691abf59c8df876331ac47b817b6 Mon Sep 17 00:00:00 2001 From: blu Date: Wed, 29 Dec 2021 19:25:54 +0200 Subject: [PATCH 15/39] code review changes --- src/etools/applications/reports/models.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/etools/applications/reports/models.py b/src/etools/applications/reports/models.py index 0c1ee92c15..645d5c21a7 100644 --- a/src/etools/applications/reports/models.py +++ b/src/etools/applications/reports/models.py @@ -836,9 +836,6 @@ class ReportingRequirement(TimeStampedModel): class Meta: ordering = ("-end_date", ) - def get_report_type_display(self): - return dict(self.TYPE_CHOICES).get(self.report_type) - def __str__(self): return "{} ({}) {}".format( self.get_report_type_display(), From 045981ff9475b49460dfbc4e64d0298362edcbe8 Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Thu, 6 Jan 2022 15:16:30 +0200 Subject: [PATCH 16/39] Code review changes: handle delete and delete selected action for agreement when having related intervention objs --- src/etools/applications/partners/admin.py | 44 ++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/etools/applications/partners/admin.py b/src/etools/applications/partners/admin.py index ecae74cb75..f2e43fab11 100644 --- a/src/etools/applications/partners/admin.py +++ b/src/etools/applications/partners/admin.py @@ -1,9 +1,11 @@ -from django.contrib import admin +from django.contrib import admin, messages +from django.contrib.admin.utils import quote from django.contrib.contenttypes.models import ContentType from django.db import models from django.forms import SelectMultiple from django.http.response import HttpResponseRedirect from django.urls import reverse +from django.utils.html import format_html from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ @@ -729,6 +731,46 @@ class AgreementAdmin( def has_module_permission(self, request): return request.user.is_superuser or request.user.groups.filter(name='Country Office Administrator').exists() + def get_deleted_objects(self, objs, request): + deleted_objects, model_count, perms_needed, protected = super().get_deleted_objects(objs, request) + if 'interventions' in model_count and model_count['interventions'] != 0: + if 'action' in request.POST and request.POST['action'] == 'delete_selected': + messages.error( + request, + _('Please delete all interventions associated with the selected Agreements ' + 'before deleting them.') + ) + else: + messages.error( + request, + _('Please delete all interventions associated with this Agreement ' + 'before deleting the agreement.') + ) + protected.extend(self.get_interventions_admin_urls(objs)) + + return deleted_objects, model_count, perms_needed, protected + + def get_interventions_admin_urls(self, objs): + urls = [] + + agreement_ids = [agreement.id for agreement in objs] if isinstance(objs, list) else \ + objs.values_list('id', flat=True) + for intervention_obj in Intervention.objects.filter(agreement_id__in=agreement_ids): + intervention_url = reverse( + 'admin:%s_%s_change' % + (intervention_obj._meta.app_label, intervention_obj._meta.model_name), + args=(quote(intervention_obj.pk),), + current_app=self.admin_site.name + ) + formatted_url = format_html( + '{} : {}', + intervention_obj._meta.model.__name__, + intervention_url, + intervention_obj + ) + urls.append(formatted_url) + return urls + class FileTypeAdmin(admin.ModelAdmin): From 7024e2281cb8745a1d7538da891d8b550e0ff4a2 Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Wed, 5 Jan 2022 18:20:52 +0300 Subject: [PATCH 17/39] fix tests broken by shifted year --- src/etools/applications/psea/tests/test_models.py | 4 ++-- src/etools/applications/reports/tests/test_synchronizers.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/etools/applications/psea/tests/test_models.py b/src/etools/applications/psea/tests/test_models.py index b869ea606e..26f732b8a5 100644 --- a/src/etools/applications/psea/tests/test_models.py +++ b/src/etools/applications/psea/tests/test_models.py @@ -195,7 +195,7 @@ def test_get_mail_context(self): "assessor": str(assessment.assessor), 'assessment_ingo_reason': None, 'assessment_type': 'UNICEF Assessment 2020', - 'reference_number': 'TST/2021PSEA{}'.format(assessment.pk), + 'reference_number': 'TST/{}PSEA{}'.format(timezone.now().year, assessment.pk), }) def test_get_reference_number(self): @@ -248,7 +248,7 @@ def test_get_mail_context(self): "assessor": str(assessment.assessor), 'assessment_ingo_reason': None, 'assessment_type': 'UNICEF Assessment 2020', - 'reference_number': 'TST/2021PSEA{}'.format(assessment.pk), + 'reference_number': 'TST/{}PSEA{}'.format(timezone.now().year, assessment.pk), }) diff --git a/src/etools/applications/reports/tests/test_synchronizers.py b/src/etools/applications/reports/tests/test_synchronizers.py index 0fe6b39679..029488fd02 100644 --- a/src/etools/applications/reports/tests/test_synchronizers.py +++ b/src/etools/applications/reports/tests/test_synchronizers.py @@ -545,7 +545,7 @@ def test_convert_records(self): self.data["OUTCOME_AREA_CODE"] = "OC_CODE" self.data["OUTCOME_DESCRIPTION"] = "OC_NAME" self.data["OUTCOME_START_DATE"] = "20-Feb-13" - self.data["OUTCOME_END_DATE"] = "20-Feb-20" + self.data["OUTCOME_END_DATE"] = "20-Feb-{}".format(str(datetime.date.today().year)[-2:]) self.data["OUTPUT_START_DATE"] = "29-Oct-44" self.data["OUTPUT_END_DATE"] = "29-Oct-44" self.data["ACTIVITY_START_DATE"] = "29-Oct-45" @@ -566,7 +566,7 @@ def test_convert_records(self): "wbs": "OC_WBS", "name": "OC_NAME", "from_date": datetime.date(2013, 2, 20), - "to_date": datetime.date(2020, 2, 20), + "to_date": datetime.date(datetime.date.today().year, 2, 20), }}, "outputs": {}, "activities": {} From 70dba03d67704529e1056cbf0328123c705cca46 Mon Sep 17 00:00:00 2001 From: Robert Avram Date: Thu, 6 Jan 2022 09:55:32 -0500 Subject: [PATCH 18/39] Update synchronizers.py --- src/etools/applications/reports/synchronizers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/etools/applications/reports/synchronizers.py b/src/etools/applications/reports/synchronizers.py index 774f961296..e46ee725e5 100644 --- a/src/etools/applications/reports/synchronizers.py +++ b/src/etools/applications/reports/synchronizers.py @@ -303,6 +303,7 @@ def _convert_records(self, records): for k in self.DATES: r[k] = datetime.datetime.strptime(r[k], INSIGHT_DATE_FORMAT).date() if r[k] else None r['HUMANITARIAN_TAG'] = r['HUMANITARIAN_TAG'] not in ['No', 'None', '0'] + return self._clean_records(records) def _save_records(self, records): From 9ce741346ae6b3f5ab78b84a358a6d196b93e51b Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Fri, 7 Jan 2022 17:47:28 +0200 Subject: [PATCH 19/39] Error on running migrations on etools-test --- .../audit/migrations/0022_engagement_reference_number.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etools/applications/audit/migrations/0022_engagement_reference_number.py b/src/etools/applications/audit/migrations/0022_engagement_reference_number.py index 95efa18b9b..a3f067cd54 100644 --- a/src/etools/applications/audit/migrations/0022_engagement_reference_number.py +++ b/src/etools/applications/audit/migrations/0022_engagement_reference_number.py @@ -10,7 +10,7 @@ def set_reference_number(apps, schema_editor): schema_name=connection.tenant.schema_name, ) for engagement in Engagement.objects.all(): - if engagement.engagement_type == engagement.TYPES.audit: + if engagement.engagement_type == 'audit': engagement_code = 'a' else: engagement_code = engagement.engagement_type @@ -36,5 +36,5 @@ class Migration(migrations.Migration): name='reference_number', field=models.CharField(max_length=100, null=True, verbose_name='Reference Number'), ), - migrations.RunPython(set_reference_number), + migrations.RunPython(set_reference_number, migrations.RunPython.noop), ] From 9d8fa133300d016640a01bca2ec55637be99f8fb Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Mon, 17 Jan 2022 17:59:02 +0200 Subject: [PATCH 20/39] [ch27976] Fix bug on update one for spot check --- src/etools/applications/audit/models.py | 2 +- src/etools/applications/partners/models.py | 57 +++++++++++-------- .../partners/tests/test_models.py | 37 ++++++++++++ 3 files changed, 72 insertions(+), 24 deletions(-) diff --git a/src/etools/applications/audit/models.py b/src/etools/applications/audit/models.py index 10a7b19989..61054205aa 100644 --- a/src/etools/applications/audit/models.py +++ b/src/etools/applications/audit/models.py @@ -456,7 +456,7 @@ def submit(self, *args, **kwargs): @transition('status', source=Engagement.STATUSES.report_submitted, target=Engagement.STATUSES.final, permission=has_action_permission(action='finalize')) def finalize(self, *args, **kwargs): - self.partner.update_spot_checks(update_one=True, event_date=self.date_of_draft_report_to_ip) + self.partner.update_spot_checks(event_date=self.date_of_draft_report_to_ip) return super().finalize(*args, **kwargs) def get_object_url(self, **kwargs): diff --git a/src/etools/applications/partners/models.py b/src/etools/applications/partners/models.py index 3427ae74ae..17cf0ae0c2 100644 --- a/src/etools/applications/partners/models.py +++ b/src/etools/applications/partners/models.py @@ -797,41 +797,52 @@ def update_programmatic_visits(self, event_date=None, update_one=False): @cached_property def spot_checks(self): from etools.applications.audit.models import Engagement, SpotCheck - return SpotCheck.objects.filter( + audit_sc = SpotCheck.objects.filter( partner=self, date_of_draft_report_to_ip__year=datetime.datetime.now().year ).exclude(status=Engagement.CANCELLED) + t2f_sc = TravelActivity.objects.filter( + travel_type=TravelType.SPOT_CHECK, + travels__status=Travel.COMPLETED, + date__year=datetime.datetime.now().year, + partner=self + ).distinct() + return { + 'audit_sc': audit_sc, + 't2f_sc': t2f_sc + } + def update_spot_checks(self, event_date=None, update_one=False): """ :return: all completed spot checks """ if not event_date: event_date = datetime.datetime.today() - quarter_name = get_quarter(event_date) - sc = self.hact_values['spot_checks']['completed']['total'] - scq = self.hact_values['spot_checks']['completed'][quarter_name] if update_one: - sc += 1 - scq += 1 - self.hact_values['spot_checks']['completed'][quarter_name] = scq + quarter_name = get_quarter(event_date) + self.hact_values['spot_checks']['completed']['total'] += 1 + self.hact_values['spot_checks']['completed'][quarter_name] += 1 else: - audit_spot_check = self.spot_checks - - asc1 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=1).count() - asc2 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=2).count() - asc3 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=3).count() - asc4 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=4).count() - - self.hact_values['spot_checks']['completed']['q1'] = asc1 - self.hact_values['spot_checks']['completed']['q2'] = asc2 - self.hact_values['spot_checks']['completed']['q3'] = asc3 - self.hact_values['spot_checks']['completed']['q4'] = asc4 - - sc = audit_spot_check.count() # TODO 1.1.9c add spot checks from field monitoring - - self.hact_values['spot_checks']['completed']['total'] = sc - self.save() + audit_sc = self.spot_checks['audit_sc'] + t2f_sc = self.spot_checks['t2f_sc'] + + a_sc1 = audit_sc.filter(date_of_draft_report_to_ip__quarter=1).count() + a_sc2 = audit_sc.filter(date_of_draft_report_to_ip__quarter=2).count() + a_sc3 = audit_sc.filter(date_of_draft_report_to_ip__quarter=3).count() + a_sc4 = audit_sc.filter(date_of_draft_report_to_ip__quarter=4).count() + + t2f_sc1 = t2f_sc.filter(date__quarter=1).count() + t2f_sc2 = t2f_sc.filter(date__quarter=2).count() + t2f_sc3 = t2f_sc.filter(date__quarter=3).count() + t2f_sc4 = t2f_sc.filter(date__quarter=4).count() + + self.hact_values['spot_checks']['completed']['q1'] = a_sc1 + t2f_sc1 + self.hact_values['spot_checks']['completed']['q2'] = a_sc2 + t2f_sc2 + self.hact_values['spot_checks']['completed']['q3'] = a_sc3 + t2f_sc3 + self.hact_values['spot_checks']['completed']['q4'] = a_sc4 + t2f_sc4 + self.hact_values['spot_checks']['completed']['total'] = audit_sc.count() + t2f_sc.count() + self.save(update_fields=['hact_values']) @cached_property def audits_completed(self): diff --git a/src/etools/applications/partners/tests/test_models.py b/src/etools/applications/partners/tests/test_models.py index 0f09a5ad1e..d400e67b03 100644 --- a/src/etools/applications/partners/tests/test_models.py +++ b/src/etools/applications/partners/tests/test_models.py @@ -541,6 +541,43 @@ def test_spot_checks_update_one_with_date(self): self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['q3'], 0) self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['q4'], 0) + @freeze_time("2013-12-26") + def test_spot_checks_update_one_true_false(self): + self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['total'], 0) + SpotCheckFactory( + partner=self.partner_organization, + status=Engagement.FINAL, + date_of_draft_report_to_ip=datetime.datetime(datetime.datetime.today().year, 12, 1) + ) + self.partner_organization.update_spot_checks(update_one=True) + tz = timezone.get_default_timezone() + traveller = UserFactory() + travel = TravelFactory( + traveler=traveller, + status=Travel.COMPLETED, + end_date=datetime.datetime(datetime.datetime.today().year, 5, 1, tzinfo=tz) + ) + date = datetime.datetime(datetime.datetime.today().year, 5, 1, tzinfo=tz) + TravelActivityFactory( + travels=[travel], + primary_traveler=traveller, + travel_type=TravelType.SPOT_CHECK, + partner=self.partner_organization, + date=date + ) + self.partner_organization.update_spot_checks(update_one=True, event_date=date) + self.partner_organization.refresh_from_db() + hact_values_update_true = copy.deepcopy(self.partner_organization.hact_values) + + self.partner_organization.update_spot_checks() + hact_values_update_false = self.partner_organization.hact_values + self.partner_organization.refresh_from_db() + + for key, value in {'total': 2, 'q1': 0, 'q2': 1, 'q3': 0, 'q4': 1}.items(): + self.assertTrue(hact_values_update_true['spot_checks']['completed'][key] == + hact_values_update_false['spot_checks']['completed'][key] == + value) + def test_spot_checks_update_travel_activity(self): self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['total'], 0) SpotCheckFactory( From 192c804e127ddea5235c3df4bfe319ea804b16a5 Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Tue, 18 Jan 2022 17:52:56 +0200 Subject: [PATCH 21/39] [ch27976] Fix update spot check: code review changes --- src/etools/applications/partners/models.py | 44 ++++++------------- .../partners/tests/test_models.py | 14 ++---- 2 files changed, 17 insertions(+), 41 deletions(-) diff --git a/src/etools/applications/partners/models.py b/src/etools/applications/partners/models.py index 17cf0ae0c2..b17f70e16e 100644 --- a/src/etools/applications/partners/models.py +++ b/src/etools/applications/partners/models.py @@ -797,21 +797,10 @@ def update_programmatic_visits(self, event_date=None, update_one=False): @cached_property def spot_checks(self): from etools.applications.audit.models import Engagement, SpotCheck - audit_sc = SpotCheck.objects.filter( + return SpotCheck.objects.filter( partner=self, date_of_draft_report_to_ip__year=datetime.datetime.now().year ).exclude(status=Engagement.CANCELLED) - t2f_sc = TravelActivity.objects.filter( - travel_type=TravelType.SPOT_CHECK, - travels__status=Travel.COMPLETED, - date__year=datetime.datetime.now().year, - partner=self - ).distinct() - return { - 'audit_sc': audit_sc, - 't2f_sc': t2f_sc - } - def update_spot_checks(self, event_date=None, update_one=False): """ :return: all completed spot checks @@ -824,24 +813,19 @@ def update_spot_checks(self, event_date=None, update_one=False): self.hact_values['spot_checks']['completed']['total'] += 1 self.hact_values['spot_checks']['completed'][quarter_name] += 1 else: - audit_sc = self.spot_checks['audit_sc'] - t2f_sc = self.spot_checks['t2f_sc'] - - a_sc1 = audit_sc.filter(date_of_draft_report_to_ip__quarter=1).count() - a_sc2 = audit_sc.filter(date_of_draft_report_to_ip__quarter=2).count() - a_sc3 = audit_sc.filter(date_of_draft_report_to_ip__quarter=3).count() - a_sc4 = audit_sc.filter(date_of_draft_report_to_ip__quarter=4).count() - - t2f_sc1 = t2f_sc.filter(date__quarter=1).count() - t2f_sc2 = t2f_sc.filter(date__quarter=2).count() - t2f_sc3 = t2f_sc.filter(date__quarter=3).count() - t2f_sc4 = t2f_sc.filter(date__quarter=4).count() - - self.hact_values['spot_checks']['completed']['q1'] = a_sc1 + t2f_sc1 - self.hact_values['spot_checks']['completed']['q2'] = a_sc2 + t2f_sc2 - self.hact_values['spot_checks']['completed']['q3'] = a_sc3 + t2f_sc3 - self.hact_values['spot_checks']['completed']['q4'] = a_sc4 + t2f_sc4 - self.hact_values['spot_checks']['completed']['total'] = audit_sc.count() + t2f_sc.count() + audit_spot_check = self.spot_checks + + asc1 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=1).count() + asc2 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=2).count() + asc3 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=3).count() + asc4 = audit_spot_check.filter(date_of_draft_report_to_ip__quarter=4).count() + + self.hact_values['spot_checks']['completed']['q1'] = asc1 + self.hact_values['spot_checks']['completed']['q2'] = asc2 + self.hact_values['spot_checks']['completed']['q3'] = asc3 + self.hact_values['spot_checks']['completed']['q4'] = asc4 + + self.hact_values['spot_checks']['completed']['total'] = audit_spot_check.count() # TODO 1.1.9c add spot checks from field monitoring self.save(update_fields=['hact_values']) @cached_property diff --git a/src/etools/applications/partners/tests/test_models.py b/src/etools/applications/partners/tests/test_models.py index d400e67b03..ce66057e25 100644 --- a/src/etools/applications/partners/tests/test_models.py +++ b/src/etools/applications/partners/tests/test_models.py @@ -551,19 +551,11 @@ def test_spot_checks_update_one_true_false(self): ) self.partner_organization.update_spot_checks(update_one=True) tz = timezone.get_default_timezone() - traveller = UserFactory() - travel = TravelFactory( - traveler=traveller, - status=Travel.COMPLETED, - end_date=datetime.datetime(datetime.datetime.today().year, 5, 1, tzinfo=tz) - ) date = datetime.datetime(datetime.datetime.today().year, 5, 1, tzinfo=tz) - TravelActivityFactory( - travels=[travel], - primary_traveler=traveller, - travel_type=TravelType.SPOT_CHECK, + SpotCheckFactory( partner=self.partner_organization, - date=date + status=Engagement.FINAL, + date_of_draft_report_to_ip=date ) self.partner_organization.update_spot_checks(update_one=True, event_date=date) self.partner_organization.refresh_from_db() From 6e0da9ab83c3c57b8af0eca4aae951d6dcad2763 Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Wed, 19 Jan 2022 12:39:19 +0200 Subject: [PATCH 22/39] [ch27828] Swagger deprecated: override index.html template for rest_framework_swagger --- .../rest_framework_swagger/index.html | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/etools/templates/rest_framework_swagger/index.html diff --git a/src/etools/templates/rest_framework_swagger/index.html b/src/etools/templates/rest_framework_swagger/index.html new file mode 100644 index 0000000000..7968d56fec --- /dev/null +++ b/src/etools/templates/rest_framework_swagger/index.html @@ -0,0 +1,70 @@ +{% load i18n %} +{% load static %} + + + + + Swagger UI + + + + {% block extra_styles %} + {# -- Add any additional CSS scripts here -- #} + {% endblock %} + + + +
+
+
+
+ + Swagger Logo + swagger + +
+ {% if USE_SESSION_AUTH %} + {% if request.user.is_authenticated %} + {% trans "Logout" %} + {% else %} + {% trans "Session Login" %} + {% endif %} + {% endif %} +
+
+
+
+ {% if USE_SESSION_AUTH %} +
+ {% block user_context_message %} + {% if request.user.is_authenticated %} + {% trans "You are logged in as: " %}{{ request.user }} + {% else %} + {% trans "Viewing as an anoymous user" %} + {% endif %} + {% endblock %} +
+ {% endif %} +
+ +
+ {% csrf_token %} + + + + + + + {% block extra_scripts %} + {# -- Add any additional scripts here -- #} + {% endblock %} + + + From 43ab85191ce964d73c5139823283c99b64ce9189 Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Wed, 26 Jan 2022 16:49:17 +0200 Subject: [PATCH 23/39] [ch28171] fix for T2F: AttributeError: 'NoneType' object has no attribute 'update_programmatic_visits' --- src/etools/applications/t2f/models.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/etools/applications/t2f/models.py b/src/etools/applications/t2f/models.py index 6695b3f41a..94e2bbeda8 100644 --- a/src/etools/applications/t2f/models.py +++ b/src/etools/applications/t2f/models.py @@ -291,11 +291,13 @@ def mark_as_completed(self): try: for act in self.activities.filter(primary_traveler=self.traveler, travel_type=TravelType.PROGRAMME_MONITORING): - act.partner.update_programmatic_visits(event_date=self.end_date, update_one=True) + if act.partner: + act.partner.update_programmatic_visits(event_date=self.end_date, update_one=True) for act in self.activities.filter(primary_traveler=self.traveler, travel_type=TravelType.SPOT_CHECK): - act.partner.update_spot_checks(event_date=self.end_date, update_one=True) + if act.partner: + act.partner.update_spot_checks(event_date=self.end_date, update_one=True) except Exception: logger.exception('Exception while trying to update hact values.') From 725aa00c77575a3a741d72b5ec2600f4c003e2c8 Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Wed, 26 Jan 2022 19:50:05 +0200 Subject: [PATCH 24/39] [ch27976] Fix on update spot check: code review changes --- src/etools/applications/audit/models.py | 1 - .../partners/tests/test_models.py | 29 ------------------- 2 files changed, 30 deletions(-) diff --git a/src/etools/applications/audit/models.py b/src/etools/applications/audit/models.py index 61054205aa..9a2815fa85 100644 --- a/src/etools/applications/audit/models.py +++ b/src/etools/applications/audit/models.py @@ -456,7 +456,6 @@ def submit(self, *args, **kwargs): @transition('status', source=Engagement.STATUSES.report_submitted, target=Engagement.STATUSES.final, permission=has_action_permission(action='finalize')) def finalize(self, *args, **kwargs): - self.partner.update_spot_checks(event_date=self.date_of_draft_report_to_ip) return super().finalize(*args, **kwargs) def get_object_url(self, **kwargs): diff --git a/src/etools/applications/partners/tests/test_models.py b/src/etools/applications/partners/tests/test_models.py index ce66057e25..0f09a5ad1e 100644 --- a/src/etools/applications/partners/tests/test_models.py +++ b/src/etools/applications/partners/tests/test_models.py @@ -541,35 +541,6 @@ def test_spot_checks_update_one_with_date(self): self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['q3'], 0) self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['q4'], 0) - @freeze_time("2013-12-26") - def test_spot_checks_update_one_true_false(self): - self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['total'], 0) - SpotCheckFactory( - partner=self.partner_organization, - status=Engagement.FINAL, - date_of_draft_report_to_ip=datetime.datetime(datetime.datetime.today().year, 12, 1) - ) - self.partner_organization.update_spot_checks(update_one=True) - tz = timezone.get_default_timezone() - date = datetime.datetime(datetime.datetime.today().year, 5, 1, tzinfo=tz) - SpotCheckFactory( - partner=self.partner_organization, - status=Engagement.FINAL, - date_of_draft_report_to_ip=date - ) - self.partner_organization.update_spot_checks(update_one=True, event_date=date) - self.partner_organization.refresh_from_db() - hact_values_update_true = copy.deepcopy(self.partner_organization.hact_values) - - self.partner_organization.update_spot_checks() - hact_values_update_false = self.partner_organization.hact_values - self.partner_organization.refresh_from_db() - - for key, value in {'total': 2, 'q1': 0, 'q2': 1, 'q3': 0, 'q4': 1}.items(): - self.assertTrue(hact_values_update_true['spot_checks']['completed'][key] == - hact_values_update_false['spot_checks']['completed'][key] == - value) - def test_spot_checks_update_travel_activity(self): self.assertEqual(self.partner_organization.hact_values['spot_checks']['completed']['total'], 0) SpotCheckFactory( From 9a6ec62bf12ad8aafced1cfc69197e99b33f6e5d Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Mon, 31 Jan 2022 13:16:52 +0200 Subject: [PATCH 25/39] [ch28232] fix for TypeError Admin activate partner staff member --- src/etools/applications/partners/forms.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/etools/applications/partners/forms.py b/src/etools/applications/partners/forms.py index 0aaf1dd57e..74ecf04403 100644 --- a/src/etools/applications/partners/forms.py +++ b/src/etools/applications/partners/forms.py @@ -92,8 +92,10 @@ def clean(self): if active and not self.instance.active: try: user = User.objects.get(email=email) - except User.DoesNotExist(): - pass + except User.DoesNotExist: + raise ValidationError( + "The staff member email {} does not match any existing user email. " + "Activation did not succeed.".format(email)) else: if self.instance.user != user: raise ValidationError({'email': self.ERROR_MESSAGES['user_mismatch']}) From e987f1177c8d12ea199c7e6a57ed2e900688140f Mon Sep 17 00:00:00 2001 From: Domenico Date: Mon, 31 Jan 2022 18:11:47 -0600 Subject: [PATCH 26/39] location import: catch exception --- src/etools/libraries/locations/tasks.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/etools/libraries/locations/tasks.py b/src/etools/libraries/locations/tasks.py index b8c40c97ad..0567462fe6 100644 --- a/src/etools/libraries/locations/tasks.py +++ b/src/etools/libraries/locations/tasks.py @@ -1,6 +1,7 @@ from django.contrib.auth import get_user_model import celery +from carto.exceptions import CartoException from celery.utils.log import get_task_logger from tenant_schemas_celery.app import get_schema_name_from_task from unicef_locations.models import CartoDBTable @@ -29,11 +30,17 @@ def __init__(self, pk, schema) -> None: ) def sync(self): - new, updated, skipped, error = super().sync() - self.log.total_records = new + updated + skipped + error - self.log.total_processed = new + updated - self.log.successful = True - self.log.save() + try: + new, updated, skipped, error = super().sync() + self.log.total_records = new + updated + skipped + error + self.log.total_processed = new + updated + self.log.successful = True + self.log.exception_message = 'Congrats: Success' + except CartoException as e: + self.log.exception_message = e + self.log.successful = False + finally: + self.log.save() def post_sync(self): # update sites From 7fa9718b443efd6d219424f9be8fe6cbfe3d7bc5 Mon Sep 17 00:00:00 2001 From: Domenico Date: Wed, 12 Jan 2022 15:06:13 -0600 Subject: [PATCH 27/39] 24369 add -> sync partner API --- src/etools/applications/partners/tasks.py | 20 +++++++--- .../partners/tests/test_api_partners.py | 25 ++++++++----- src/etools/applications/partners/urls_v2.py | 3 +- .../partners/views/partner_organization_v2.py | 37 +++---------------- 4 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/etools/applications/partners/tasks.py b/src/etools/applications/partners/tasks.py index 388eb31de1..5ff24207bb 100644 --- a/src/etools/applications/partners/tasks.py +++ b/src/etools/applications/partners/tasks.py @@ -297,14 +297,24 @@ def check_intervention_past_start(): def sync_partner(vendor_number=None, country=None): from etools.applications.partners.synchronizers import PartnerSynchronizer try: - valid_response, response = get_data_from_insight('partners/?vendor={vendor_code}', - {"vendor_code": vendor_number}) + valid_response, response = get_data_from_insight( + 'partners/?vendor={vendor_code}', { + "vendor_code": vendor_number, + "businessarea": country.business_area_code + }) + + if "ROWSET" not in response: + logger.exception("{} sync failed: Invalid response".format(PartnerSynchronizer.__name__)) + return 'The vendor number could not be found in INSIGHT' + partner_resp = response["ROWSET"]["ROW"] partner_sync = PartnerSynchronizer(business_area_code=country.business_area_code) if not partner_sync._filter_records([partner_resp]): - raise VisionException + raise VisionException('Partner skipped because one or more of the required fields are missing') partner_sync._partner_save(partner_resp, full_sync=False) - except VisionException: + except VisionException as e: logger.exception("{} sync failed".format(PartnerSynchronizer.__name__)) - logger.info('Partner {} synced successfully.'.format(vendor_number)) + return str(e) + else: + logger.info('Partner {} synced successfully.'.format(vendor_number)) diff --git a/src/etools/applications/partners/tests/test_api_partners.py b/src/etools/applications/partners/tests/test_api_partners.py index 4cf82b4a8d..5359756baa 100644 --- a/src/etools/applications/partners/tests/test_api_partners.py +++ b/src/etools/applications/partners/tests/test_api_partners.py @@ -56,7 +56,7 @@ from etools.applications.users.tests.factories import GroupFactory, UserFactory from etools.libraries.pythonlib.datetime import get_quarter -INSIGHT_PATH = "etools.applications.partners.views.partner_organization_v2.get_data_from_insight" +INSIGHT_PATH = "etools.applications.partners.tasks.get_data_from_insight" class URLsTestCase(URLAssertionMixin, SimpleTestCase): @@ -776,7 +776,7 @@ def test_no_vendor_number(self): ) def test_no_insight_reponse(self): - mock_insight = Mock(return_value=(False, "Insight Failed")) + mock_insight = Mock(return_value=(False, "The vendor number could not be found in INSIGHT")) with patch(INSIGHT_PATH, mock_insight): response = self.forced_auth_req( 'post', @@ -785,13 +785,23 @@ def test_no_insight_reponse(self): view=self.view ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual(response.data, {"error": "Insight Failed"}) + self.assertEqual(response.data, {"error": "The vendor number could not be found in INSIGHT"}) def test_vendor_exists(self): PartnerFactory(vendor_number="321") mock_insight = Mock(return_value=(True, { "ROWSET": { - "ROW": {"VENDOR_CODE": "321"} + "ROW": { + 'VENDOR_CODE': '321', + 'PARTNER_TYPE_DESC': 'Test', + 'VENDOR_NAME': 'Vendor', + 'COUNTRY': 'Italy', + 'TOTAL_CASH_TRANSFERRED_CP': 2000, + 'TOTAL_CASH_TRANSFERRED_CY': 1000, + 'NET_CASH_TRANSFERRED_CY': 500, + 'REPORTED_CY': 250, + 'TOTAL_CASH_TRANSFERRED_YTD': 125 + } } })) with patch(INSIGHT_PATH, mock_insight): @@ -801,11 +811,8 @@ def test_vendor_exists(self): data={}, view=self.view ) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual( - response.data, - {"error": "This vendor number already exists in eTools"} - ) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertTrue(response.data) def test_missing_required_keys(self): mock_insight = Mock(return_value=(True, { diff --git a/src/etools/applications/partners/urls_v2.py b/src/etools/applications/partners/urls_v2.py index 36227d7a5d..ecf984dc2e 100644 --- a/src/etools/applications/partners/urls_v2.py +++ b/src/etools/applications/partners/urls_v2.py @@ -126,7 +126,8 @@ re_path(r'^partners/assessments/(?P\d+)/$', view=PartnerOrganizationAssessmentUpdateDeleteView.as_view(http_method_names=['delete', 'patch']), name='partner-assessment-detail'), - re_path(r'^partners/add/$', view=PartnerOrganizationAddView.as_view(http_method_names=['post']), name='partner-add'), + re_path(r'^partners/add/$', view=PartnerOrganizationAddView.as_view(http_method_names=['post']), + name='partner-add'), re_path(r'^partners/(?P\d+)/staff-members/$', view=PartnerStaffMemberListAPIVIew.as_view(http_method_names=['get']), diff --git a/src/etools/applications/partners/views/partner_organization_v2.py b/src/etools/applications/partners/views/partner_organization_v2.py index 44d7b893fd..3b303bca8a 100644 --- a/src/etools/applications/partners/views/partner_organization_v2.py +++ b/src/etools/applications/partners/views/partner_organization_v2.py @@ -20,7 +20,6 @@ from rest_framework.response import Response from rest_framework_csv import renderers as r from unicef_restlib.views import QueryStringFilterMixin -from unicef_vision.utils import get_data_from_insight from etools.applications.action_points.models import ActionPoint from etools.applications.core.mixins import ExportModelMixin @@ -70,7 +69,7 @@ PlannedEngagementNestedSerializer, PlannedEngagementSerializer, ) -from etools.applications.partners.synchronizers import PartnerSynchronizer +from etools.applications.partners.tasks import sync_partner from etools.applications.partners.views.helpers import set_tenant_or_fail from etools.applications.t2f.models import Travel, TravelActivity, TravelType from etools.applications.utils.pagination import AppendablePageNumberPagination @@ -460,10 +459,7 @@ def delete(self, request, *args, **kwargs): class PartnerOrganizationAddView(CreateAPIView): - """ - Create new Partners. - Returns a list of Partners. - """ + """Sync Partner given a vendor number (it creates it if it does not exist)""" serializer_class = PartnerOrganizationCreateUpdateSerializer permission_classes = (PartnershipManagerPermission,) @@ -474,32 +470,11 @@ def create(self, request, *args, **kwargs): return Response({"error": "No vendor number provided for Partner Organization"}, status=status.HTTP_400_BAD_REQUEST) - valid_response, response = get_data_from_insight('partners/?vendor={vendor_code}', - {"vendor_code": vendor}) - - if valid_response and "ROWSET" not in response: - return Response({"error": "The vendor number could not be found in Insight"}, status=status.HTTP_400_BAD_REQUEST) - - if not valid_response or "ROWSET" not in response: - return Response({"error": response}, status=status.HTTP_400_BAD_REQUEST) - - partner_resp = response["ROWSET"]["ROW"] - - if PartnerOrganization.objects.filter( - vendor_number=partner_resp[PartnerSynchronizer.MAPPING['vendor_number']]).exists(): - return Response({"error": 'This vendor number already exists in eTools'}, - status=status.HTTP_400_BAD_REQUEST) - - country = request.user.profile.country - partner_sync = PartnerSynchronizer(business_area_code=country.business_area_code) - - if not partner_sync._filter_records([partner_resp]): - return Response({"error": 'Partner skipped because one or more of the required fields are missing'}, - status=status.HTTP_400_BAD_REQUEST) - partner_sync._partner_save(partner_resp, full_sync=False) + error = sync_partner(vendor, request.user.profile.country) + if error: + return Response({"error": error}, status=status.HTTP_400_BAD_REQUEST) - partner = PartnerOrganization.objects.get( - vendor_number=partner_resp[PartnerSynchronizer.MAPPING['vendor_number']]) + partner = PartnerOrganization.objects.get(vendor_number=vendor) po_serializer = PartnerOrganizationDetailSerializer(partner) return Response(po_serializer.data, status=status.HTTP_201_CREATED) From 5d7d2c832d32399faed1fdc747e9087c77dbaa69 Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Thu, 3 Feb 2022 17:03:38 +0200 Subject: [PATCH 28/39] [ch28232] pass error on staff member activation when no auth user is found --- src/etools/applications/partners/forms.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/etools/applications/partners/forms.py b/src/etools/applications/partners/forms.py index 74ecf04403..201cd3e810 100644 --- a/src/etools/applications/partners/forms.py +++ b/src/etools/applications/partners/forms.py @@ -93,9 +93,7 @@ def clean(self): try: user = User.objects.get(email=email) except User.DoesNotExist: - raise ValidationError( - "The staff member email {} does not match any existing user email. " - "Activation did not succeed.".format(email)) + pass else: if self.instance.user != user: raise ValidationError({'email': self.ERROR_MESSAGES['user_mismatch']}) From b6bf7c0d3d0b07f1bd360635c86a9c923ce28142 Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Fri, 4 Feb 2022 11:47:56 +0300 Subject: [PATCH 29/39] move activity findings to summary if only one answer is available --- .../data_collection/tests/test_views.py | 45 +++++++++++++++++++ .../field_monitoring/planning/models.py | 11 ++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/etools/applications/field_monitoring/data_collection/tests/test_views.py b/src/etools/applications/field_monitoring/data_collection/tests/test_views.py index 2af4c89332..a85f871195 100644 --- a/src/etools/applications/field_monitoring/data_collection/tests/test_views.py +++ b/src/etools/applications/field_monitoring/data_collection/tests/test_views.py @@ -533,6 +533,51 @@ def test_update_visit_lead(self): def test_update_fm_user(self): self._test_update(self.fm_user, self.finding, {}, expected_status=status.HTTP_403_FORBIDDEN) + def test_activity_answers_porting_no_answers(self): + method = self.activity_question.question.methods.first() + StartedChecklistFactory(monitoring_activity=self.activity, method=method) + + self.activity.port_findings_to_summary() + + self.activity_question.overall_finding.refresh_from_db() + activity_finding = self.activity_question.overall_finding + self.assertIsNone(activity_finding.value) + + def test_activity_answers_porting_one_answer(self): + StartedChecklistFactory( + monitoring_activity=self.activity, + method=self.activity_question.question.methods.first(), + ) + + finding = self.started_checklist.findings.filter(activity_question=self.activity_question).first() + finding.value = 'test value' + finding.save() + + self.activity.port_findings_to_summary() + + self.activity_question.overall_finding.refresh_from_db() + activity_finding = self.activity_question.overall_finding + self.assertEqual(activity_finding.value, 'test value') + + def test_activity_answers_porting_two_answers(self): + second_checklist = StartedChecklistFactory( + monitoring_activity=self.activity, + method=self.activity_question.question.methods.first(), + ) + + finding = self.started_checklist.findings.filter(activity_question=self.activity_question).first() + finding.value = 'test value' + finding.save() + finding = second_checklist.findings.filter(activity_question=self.activity_question).first() + finding.value = 'another value' + finding.save() + + self.activity.port_findings_to_summary() + + self.activity_question.overall_finding.refresh_from_db() + activity_finding = self.activity_question.overall_finding + self.assertIsNone(activity_finding.value) + class TestActivityOverallFindingsView(ChecklistDataCollectionTestMixin, APIViewSetTestCase): base_view = 'field_monitoring_data_collection:activity-overall-findings' diff --git a/src/etools/applications/field_monitoring/planning/models.py b/src/etools/applications/field_monitoring/planning/models.py index b9e16507a6..16e2cdfe7e 100644 --- a/src/etools/applications/field_monitoring/planning/models.py +++ b/src/etools/applications/field_monitoring/planning/models.py @@ -1,7 +1,7 @@ from django.conf import settings from django.contrib.contenttypes.fields import GenericRelation from django.db import connection, models -from django.db.models import Exists, OuterRef, Q +from django.db.models import Count, Exists, OuterRef, Q from django.db.models.base import ModelBase from django.utils.translation import gettext_lazy as _ @@ -193,6 +193,7 @@ class MonitoringActivity( ], STATUSES.report_finalization: [ lambda i, old_instance=None, user=None: i.close_offline_blueprints(), + lambda i, old_instance=None, user=None: i.port_findings_to_summary(), ], STATUSES.submitted: [ lambda i, old_instance=None, user=None: i.send_submit_notice(), @@ -577,6 +578,14 @@ def init_offline_blueprints(self): def close_offline_blueprints(self): MonitoringActivityOfflineSynchronizer(self).close_blueprints() + def port_findings_to_summary(self): + valid_questions = self.questions.annotate( + answers_count=Count('findings', filter=Q(findings__value__isnull=False)), + ).filter(answers_count=1).prefetch_related('findings') + for question in valid_questions: + question.overall_finding.value = question.findings.all()[0].value + question.overall_finding.save() + class MonitoringActivityActionPointManager(models.Manager): def get_queryset(self): From c27cb7cc4301658286a95f4080eb3d97ba46c42f Mon Sep 17 00:00:00 2001 From: Roman Karpovich Date: Fri, 4 Feb 2022 12:21:57 +0300 Subject: [PATCH 30/39] transfer narrative findings to activity overall --- .../data_collection/tests/test_views.py | 20 +++++++++++++++++++ .../field_monitoring/planning/models.py | 14 +++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/etools/applications/field_monitoring/data_collection/tests/test_views.py b/src/etools/applications/field_monitoring/data_collection/tests/test_views.py index a85f871195..10a76dda9b 100644 --- a/src/etools/applications/field_monitoring/data_collection/tests/test_views.py +++ b/src/etools/applications/field_monitoring/data_collection/tests/test_views.py @@ -543,6 +543,9 @@ def test_activity_answers_porting_no_answers(self): activity_finding = self.activity_question.overall_finding self.assertIsNone(activity_finding.value) + activity_overall_finding = self.activity.overall_findings.first() + self.assertEqual(activity_overall_finding.narrative_finding, '') + def test_activity_answers_porting_one_answer(self): StartedChecklistFactory( monitoring_activity=self.activity, @@ -553,12 +556,19 @@ def test_activity_answers_porting_one_answer(self): finding.value = 'test value' finding.save() + overall_finding = self.started_checklist.overall_findings.first() + overall_finding.narrative_finding = 'ok' + overall_finding.save() + self.activity.port_findings_to_summary() self.activity_question.overall_finding.refresh_from_db() activity_finding = self.activity_question.overall_finding self.assertEqual(activity_finding.value, 'test value') + activity_overall_finding = self.activity.overall_findings.first() + self.assertEqual(activity_overall_finding.narrative_finding, 'ok') + def test_activity_answers_porting_two_answers(self): second_checklist = StartedChecklistFactory( monitoring_activity=self.activity, @@ -572,12 +582,22 @@ def test_activity_answers_porting_two_answers(self): finding.value = 'another value' finding.save() + overall_finding = self.started_checklist.overall_findings.first() + overall_finding.narrative_finding = 'ok' + overall_finding.save() + second_overall_finding = second_checklist.overall_findings.first() + second_overall_finding.narrative_finding = 'fine' + second_overall_finding.save() + self.activity.port_findings_to_summary() self.activity_question.overall_finding.refresh_from_db() activity_finding = self.activity_question.overall_finding self.assertIsNone(activity_finding.value) + activity_overall_finding = self.activity.overall_findings.first() + self.assertEqual(activity_overall_finding.narrative_finding, '') + class TestActivityOverallFindingsView(ChecklistDataCollectionTestMixin, APIViewSetTestCase): base_view = 'field_monitoring_data_collection:activity-overall-findings' diff --git a/src/etools/applications/field_monitoring/planning/models.py b/src/etools/applications/field_monitoring/planning/models.py index 16e2cdfe7e..49a3f41b8c 100644 --- a/src/etools/applications/field_monitoring/planning/models.py +++ b/src/etools/applications/field_monitoring/planning/models.py @@ -579,6 +579,8 @@ def close_offline_blueprints(self): MonitoringActivityOfflineSynchronizer(self).close_blueprints() def port_findings_to_summary(self): + from etools.applications.field_monitoring.data_collection.models import ChecklistOverallFinding + valid_questions = self.questions.annotate( answers_count=Count('findings', filter=Q(findings__value__isnull=False)), ).filter(answers_count=1).prefetch_related('findings') @@ -586,6 +588,18 @@ def port_findings_to_summary(self): question.overall_finding.value = question.findings.all()[0].value question.overall_finding.save() + for overall_finding in self.overall_findings.all(): + narrative_findings = ChecklistOverallFinding.objects.filter( + ~Q(narrative_finding=''), + started_checklist__monitoring_activity=self, + partner=overall_finding.partner, + cp_output=overall_finding.cp_output, + intervention=overall_finding.intervention, + ).values_list('narrative_finding', flat=True) + if len(narrative_findings) == 1: + overall_finding.narrative_finding = narrative_findings[0] + overall_finding.save() + class MonitoringActivityActionPointManager(models.Manager): def get_queryset(self): From 5e9bdd28844fb31cbd95e673b2f1efe3b3c2544c Mon Sep 17 00:00:00 2001 From: Domenico Date: Tue, 8 Feb 2022 10:37:35 -0600 Subject: [PATCH 31/39] location 3.2 --- Pipfile | 2 +- Pipfile.lock | 748 ++++++++++-------- .../analyze/tests/test_views.py | 2 +- .../field_monitoring/analyze/views.py | 2 +- .../fm_settings/export/serializers.py | 2 +- .../field_monitoring/fm_settings/models.py | 2 +- .../fm_settings/tests/factories.py | 4 +- .../fm_settings/tests/test_models.py | 2 +- .../fm_settings/tests/test_views.py | 22 +- .../field_monitoring/fm_settings/views.py | 6 +- .../field_monitoring/planning/views.py | 2 +- .../applications/management/serializers.py | 3 - .../management/tests/test_views.py | 14 +- .../partners/serializers/interventions_v2.py | 2 +- .../partners/serializers/prp_v1.py | 13 +- .../tests/data/prp-intervention-list.json | 2 +- .../partners/tests/test_api_pmp.py | 8 +- .../partners/tests/test_api_prp.py | 8 +- .../applications/partners/tests/test_utils.py | 3 +- src/etools/applications/partners/views/v2.py | 4 +- .../applications/users/tests/test_admin.py | 2 +- src/etools/config/settings/base.py | 2 + src/etools/config/urls.py | 2 - src/etools/libraries/locations/admin.py | 3 +- .../libraries/locations/tests/test_views.py | 15 +- src/etools/libraries/locations/urls.py | 9 +- src/etools/libraries/locations/views.py | 4 - 27 files changed, 466 insertions(+), 422 deletions(-) diff --git a/Pipfile b/Pipfile index c01d04c943..27419819c3 100644 --- a/Pipfile +++ b/Pipfile @@ -74,7 +74,7 @@ social-auth-core = {extras = ["azuread"],version = "==4.1"} tenant-schemas-celery = "==1.0.1" unicef-attachments = "==0.10.1" unicef-djangolib = "==0.5.4" -unicef-locations = "==3.1" +unicef-locations = "==3.2.1" unicef-notification = "==1.1" unicef-restlib = "==0.7" unicef-snapshot = "==1.1" diff --git a/Pipfile.lock b/Pipfile.lock index 3add5f1ee4..9c920c24f8 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "bfdcf8edbf2ccb62e4fbcd8be1f972d8ede32b7dc4fedd388acaacb859782004" + "sha256": "76c4cabb1d1868637c79256e8ffb996c7028586dba6094dd86d724affebc2e6a" }, "pipfile-spec": 6, "requires": { @@ -18,10 +18,10 @@ "default": { "amqp": { "hashes": [ - "sha256:03e16e94f2b34c31f8bf1206d8ddd3ccaa4c315f7f6a1879b7b1210d229568c2", - "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb" + "sha256:1e5f707424e544078ca196e72ae6a14887ce74e02bd126be54b7c03c971bef18", + "sha256:9cd81f7b023fc04bbb108718fbac674f06901b77bfcdce85b10e2a5d0ee91be5" ], - "version": "==5.0.6" + "version": "==5.0.9" }, "arabic-reshaper": { "hashes": [ @@ -33,10 +33,10 @@ }, "asgiref": { "hashes": [ - "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9", - "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214" + "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0", + "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9" ], - "version": "==3.4.1" + "version": "==3.5.0" }, "azure-common": { "hashes": [ @@ -156,11 +156,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721", - "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c" + "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45", + "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c" ], "markers": "python_version >= '3'", - "version": "==2.0.9" + "version": "==2.0.11" }, "click": { "hashes": [ @@ -263,10 +263,10 @@ }, "django-admin-extra-urls": { "hashes": [ - "sha256:fc68efd40569f2301cb329a0c445dd3517b0aa9c03c1ab7d9fc8a006d22de9b8" + "sha256:b896eebc24779081f5bb5015c41fb12a741c61d520eec88688749e4991f7cbf5" ], "index": "pypi", - "version": "==3.5.1" + "version": "==4.1.1" }, "django-appconf": { "hashes": [ @@ -278,9 +278,9 @@ }, "django-autocomplete-light": { "hashes": [ - "sha256:25f0ea71b59a8f1f97a8a564e33e429570b0ea77c5eac81f7beb283073b4ba90" + "sha256:50bc562fe13c206cf53304d7f6a8b929729016ab1dae64d6176d4ccd6caff6ab" ], - "version": "==3.8.2" + "version": "==3.9.1" }, "django-celery-beat": { "hashes": [ @@ -596,10 +596,10 @@ }, "humanize": { "hashes": [ - "sha256:12f113f2e369dac7f35d3823f49262934f4a22a53a6d3d4c86b736f50db88c7b", - "sha256:a6f7cc1597db69a4e571ad5e19b4da07ee871da5a9de2b233dbfab02d98e9754" + "sha256:32bcf712ac98ff5e73627a9d31e1ba5650619008d6d13543b5d53b48e8ab8d43", + "sha256:60dd8c952b1df1ad83f0903844dec50a34ba7a04eea22a6b14204ffb62dbb0a4" ], - "version": "==3.13.1" + "version": "==3.14.0" }, "idna": { "hashes": [ @@ -639,75 +639,75 @@ }, "kombu": { "hashes": [ - "sha256:0f5d0763fb916808f617b886697b2be28e6bc35026f08e679697fc814b48a608", - "sha256:d36f0cde6a18d9eb7b6b3aa62a59bfdff7f5724689850e447eca5be8efc9d501" + "sha256:81a90c1de97e08d3db37dbf163eaaf667445e1068c98bfd89f051a40e9f6dbbd", + "sha256:eeaeb8024f3a5cfc71c9250e45cddb8493f269d74ada2f74909a93c59c4b4179" ], - "version": "==5.2.2" + "version": "==5.2.3" }, "lxml": { "hashes": [ - "sha256:08eb9200d88b376a8ed5e50f1dc1d1a45b49305169674002a3b5929943390591", - "sha256:0b12c95542f04d10cba46b3ff28ea52ea56995b78cf918f0b11b05e75812bb79", - "sha256:0c15e1cd55055956e77b0732270f1c6005850696bc3ef3e03d01e78af84eaa42", - "sha256:15d0381feb56f08f78c5cc4fc385ddfe0bde1456e37f54a9322833371aec4060", - "sha256:197b7cb7a753cf553a45115739afd8458464a28913da00f5c525063f94cd3f48", - "sha256:20d7c8d90d449c6a353b15ee0459abae8395dbe59ad01e406ccbf30cd81c6f98", - "sha256:240db6f3228d26e3c6f4fad914b9ddaaf8707254e8b3efd564dc680c8ec3c264", - "sha256:2901625f4a878a055d275beedc20ba9cb359cefc4386a967222fee29eb236038", - "sha256:2b06a91cf7b8acea7793006e4ae50646cef0fe35ce5acd4f5cb1c77eb228e4a1", - "sha256:2eb90f6ec3c236ef2f1bb38aee7c0d23e77d423d395af6326e7cca637519a4cb", - "sha256:351482da8dd028834028537f08724b1de22d40dcf3bb723b469446564f409074", - "sha256:35752ee40f7bbf6adc9ff4e1f4b84794a3593736dcce80db32e3c2aa85e294ac", - "sha256:38b9de0de3aa689fe9fb9877ae1be1e83b8cf9621f7e62049d0436b9ecf4ad64", - "sha256:433df8c7dde0f9e41cbf4f36b0829d50a378116ef5e962ba3881f2f5f025c7be", - "sha256:4341d135f5660db10184963d9c3418c3e28d7f868aaf8b11a323ebf85813f7f4", - "sha256:45fdb2899c755138722797161547a40b3e2a06feda620cc41195ee7e97806d81", - "sha256:4717123f7c11c81e0da69989e5a64079c3f402b0efeb4c6241db6c369d657bd8", - "sha256:47e955112ce64241fdb357acf0216081f9f3255b3ac9c502ca4b3323ec1ca558", - "sha256:48eaac2991b3036175b42ee8d3c23f4cca13f2be8426bf29401a690ab58c88f4", - "sha256:4aa349c5567651f34d4eaae7de6ed5b523f6d70a288f9c6fbac22d13a0784e04", - "sha256:4ba74afe5ee5cb5e28d83b513a6e8f0875fda1dc1a9aea42cc0065f029160d2a", - "sha256:4ec9a80dd5704ecfde54319b6964368daf02848c8954d3bacb9b64d1c7659159", - "sha256:50790313df028aa05cf22be9a8da033b86c42fa32523e4fd944827b482b17bf0", - "sha256:51a0e5d243687596f46e24e464121d4b232ad772e2d1785b2a2c0eb413c285d4", - "sha256:523f195948a1ba4f9f5b7294d83c6cd876547dc741820750a7e5e893a24bbe38", - "sha256:543b239b191bb3b6d9bef5f09f1fb2be5b7eb09ab4d386aa655e4d53fbe9ff47", - "sha256:5ff5bb2a198ea67403bb6818705e9a4f90e0313f2215428ec51001ce56d939fb", - "sha256:601f0ab75538b280aaf1e720eb9d68d4fa104ac274e1e9e6971df488f4dcdb0f", - "sha256:6020c70ff695106bf80651953a23e37718ef1fee9abd060dcad8e32ab2dc13f3", - "sha256:619c6d2b552bba00491e96c0518aad94002651c108a0f7364ff2d7798812c00e", - "sha256:6298f5b42a26581206ef63fffa97c754245d329414108707c525512a5197f2ba", - "sha256:662523cd2a0246740225c7e32531f2e766544122e58bee70e700a024cfc0cf81", - "sha256:6764998345552b1dfc9326a932d2bad6367c6b37a176bb73ada6b9486bf602f7", - "sha256:6d422b3c729737d8a39279a25fa156c983a56458f8b2f97661ee6fb22b80b1d6", - "sha256:72e730d33fe2e302fd07285f14624fca5e5e2fb2bb4fb2c3941e318c41c443d1", - "sha256:75d3c5bbc0ddbad03bb68b9be638599f67e4b98ed3dcd0fec9f6f39e41ee96cb", - "sha256:7ae7089d81fc502df4b217ad77f03c54039fe90dac0acbe70448d7e53bfbc57e", - "sha256:80d10d53d3184837445ff8562021bdd37f57c4cadacbf9d8726cc16220a00d54", - "sha256:877666418598f6cb289546c77ff87590cfd212f903b522b0afa0b9fb73b3ccfb", - "sha256:9b87727561c1150c0cc91c5d9d389448b37a7d15f0ba939ed3d1acb2f11bf6c5", - "sha256:9c91a73971a922c13070fd8fa5a114c858251791ba2122a941e6aa781c713e44", - "sha256:9db24803fa71e3305fe4a7812782b708da21a0b774b130dd1860cf40a6d7a3ee", - "sha256:a75c1ad05eedb1a3ff2a34a52a4f0836cfaa892e12796ba39a7732c82701eff4", - "sha256:a77a3470ba37e11872c75ca95baf9b3312133a3d5a5dc720803b23098c653976", - "sha256:ab6db93a2b6b66cbf62b4e4a7135f476e708e8c5c990d186584142c77d7f975a", - "sha256:afd60230ad9d8bcba005945ec3a343722f09e0b7f8ae804246e5d2cfc6bd71a6", - "sha256:b0ca0ada9d3bc18bd6f611bd001a28abdd49ab9698bd6d717f7f5394c8e94628", - "sha256:b567178a74a2261345890eac66fbf394692a6e002709d329f28a673ca6042473", - "sha256:b667c51682fe9b9788c69465956baa8b6999531876ccedcafc895c74ad716cd8", - "sha256:bbf2dc330bd44bfc0254ab37677ec60f7c7ecea55ad8ba1b8b2ea7bf20c265f5", - "sha256:bdc224f216ead849e902151112efef6e96c41ee1322e15d4e5f7c8a826929aee", - "sha256:cf201bf5594d1aab139fe53e3fca457e4f8204a5bbd65d48ab3b82a16f517868", - "sha256:d43bd68714049c84e297c005456a15ecdec818f7b5aa5868c8b0a865cfb78a44", - "sha256:daf9bd1fee31f1c7a5928b3e1059e09a8d683ea58fb3ffc773b6c88cb8d1399c", - "sha256:e678a643177c0e5ec947b645fa7bc84260dfb9b6bf8fb1fdd83008dfc2ca5928", - "sha256:e91d24623e747eeb2d8121f4a94c6a7ad27dc48e747e2dc95bfe88632bd028a2", - "sha256:e95da348d57eb448d226a44b868ff2ca5786fbcbe417ac99ff62d0a7d724b9c7", - "sha256:ee9e4b07b0eba4b6a521509e9e1877476729c1243246b6959de697ebea739643", - "sha256:f5dd358536b8a964bf6bd48de038754c1609e72e5f17f5d21efe2dda17594dbf", - "sha256:ffd65cfa33fed01735c82aca640fde4cc63f0414775cba11e06f84fae2085a6e" - ], - "version": "==4.6.4" + "sha256:0607ff0988ad7e173e5ddf7bf55ee65534bd18a5461183c33e8e41a59e89edf4", + "sha256:09b738360af8cb2da275998a8bf79517a71225b0de41ab47339c2beebfff025f", + "sha256:0a5f0e4747f31cff87d1eb32a6000bde1e603107f632ef4666be0dc065889c7a", + "sha256:0b5e96e25e70917b28a5391c2ed3ffc6156513d3db0e1476c5253fcd50f7a944", + "sha256:1104a8d47967a414a436007c52f533e933e5d52574cab407b1e49a4e9b5ddbd1", + "sha256:13dbb5c7e8f3b6a2cf6e10b0948cacb2f4c9eb05029fe31c60592d08ac63180d", + "sha256:2a906c3890da6a63224d551c2967413b8790a6357a80bf6b257c9a7978c2c42d", + "sha256:317bd63870b4d875af3c1be1b19202de34c32623609ec803b81c99193a788c1e", + "sha256:34c22eb8c819d59cec4444d9eebe2e38b95d3dcdafe08965853f8799fd71161d", + "sha256:36b16fecb10246e599f178dd74f313cbdc9f41c56e77d52100d1361eed24f51a", + "sha256:38d9759733aa04fb1697d717bfabbedb21398046bd07734be7cccc3d19ea8675", + "sha256:3e26ad9bc48d610bf6cc76c506b9e5ad9360ed7a945d9be3b5b2c8535a0145e3", + "sha256:41358bfd24425c1673f184d7c26c6ae91943fe51dfecc3603b5e08187b4bcc55", + "sha256:447d5009d6b5447b2f237395d0018901dcc673f7d9f82ba26c1b9f9c3b444b60", + "sha256:44f552e0da3c8ee3c28e2eb82b0b784200631687fc6a71277ea8ab0828780e7d", + "sha256:490712b91c65988012e866c411a40cc65b595929ececf75eeb4c79fcc3bc80a6", + "sha256:4c093c571bc3da9ebcd484e001ba18b8452903cd428c0bc926d9b0141bcb710e", + "sha256:50d3dba341f1e583265c1a808e897b4159208d814ab07530202b6036a4d86da5", + "sha256:534e946bce61fd162af02bad7bfd2daec1521b71d27238869c23a672146c34a5", + "sha256:585ea241ee4961dc18a95e2f5581dbc26285fcf330e007459688096f76be8c42", + "sha256:59e7da839a1238807226f7143c68a479dee09244d1b3cf8c134f2fce777d12d0", + "sha256:5b0f782f0e03555c55e37d93d7a57454efe7495dab33ba0ccd2dbe25fc50f05d", + "sha256:5bee1b0cbfdb87686a7fb0e46f1d8bd34d52d6932c0723a86de1cc532b1aa489", + "sha256:610807cea990fd545b1559466971649e69302c8a9472cefe1d6d48a1dee97440", + "sha256:6308062534323f0d3edb4e702a0e26a76ca9e0e23ff99be5d82750772df32a9e", + "sha256:67fa5f028e8a01e1d7944a9fb616d1d0510d5d38b0c41708310bd1bc45ae89f6", + "sha256:6a2ab9d089324d77bb81745b01f4aeffe4094306d939e92ba5e71e9a6b99b71e", + "sha256:6c198bfc169419c09b85ab10cb0f572744e686f40d1e7f4ed09061284fc1303f", + "sha256:6e56521538f19c4a6690f439fefed551f0b296bd785adc67c1777c348beb943d", + "sha256:6ec829058785d028f467be70cd195cd0aaf1a763e4d09822584ede8c9eaa4b03", + "sha256:718d7208b9c2d86aaf0294d9381a6acb0158b5ff0f3515902751404e318e02c9", + "sha256:735e3b4ce9c0616e85f302f109bdc6e425ba1670a73f962c9f6b98a6d51b77c9", + "sha256:772057fba283c095db8c8ecde4634717a35c47061d24f889468dc67190327bcd", + "sha256:7b5e2acefd33c259c4a2e157119c4373c8773cf6793e225006a1649672ab47a6", + "sha256:82d16a64236970cb93c8d63ad18c5b9f138a704331e4b916b2737ddfad14e0c4", + "sha256:87c1b0496e8c87ec9db5383e30042357b4839b46c2d556abd49ec770ce2ad868", + "sha256:8e54945dd2eeb50925500957c7c579df3cd07c29db7810b83cf30495d79af267", + "sha256:9393a05b126a7e187f3e38758255e0edf948a65b22c377414002d488221fdaa2", + "sha256:9fbc0dee7ff5f15c4428775e6fa3ed20003140560ffa22b88326669d53b3c0f4", + "sha256:a1613838aa6b89af4ba10a0f3a972836128801ed008078f8c1244e65958f1b24", + "sha256:a1bbc4efa99ed1310b5009ce7f3a1784698082ed2c1ef3895332f5df9b3b92c2", + "sha256:a555e06566c6dc167fbcd0ad507ff05fd9328502aefc963cb0a0547cfe7f00db", + "sha256:a58d78653ae422df6837dd4ca0036610b8cb4962b5cfdbd337b7b24de9e5f98a", + "sha256:a5edc58d631170de90e50adc2cc0248083541affef82f8cd93bea458e4d96db8", + "sha256:a5f623aeaa24f71fce3177d7fee875371345eb9102b355b882243e33e04b7175", + "sha256:adaab25be351fff0d8a691c4f09153647804d09a87a4e4ea2c3f9fe9e8651851", + "sha256:ade74f5e3a0fd17df5782896ddca7ddb998845a5f7cd4b0be771e1ffc3b9aa5b", + "sha256:b1d381f58fcc3e63fcc0ea4f0a38335163883267f77e4c6e22d7a30877218a0e", + "sha256:bf6005708fc2e2c89a083f258b97709559a95f9a7a03e59f805dd23c93bc3986", + "sha256:d546431636edb1d6a608b348dd58cc9841b81f4116745857b6cb9f8dadb2725f", + "sha256:d5618d49de6ba63fe4510bdada62d06a8acfca0b4b5c904956c777d28382b419", + "sha256:dfd0d464f3d86a1460683cd742306d1138b4e99b79094f4e07e1ca85ee267fe7", + "sha256:e18281a7d80d76b66a9f9e68a98cf7e1d153182772400d9a9ce855264d7d0ce7", + "sha256:e410cf3a2272d0a85526d700782a2fa92c1e304fdcc519ba74ac80b8297adf36", + "sha256:e662c6266e3a275bdcb6bb049edc7cd77d0b0f7e119a53101d367c841afc66dc", + "sha256:ec9027d0beb785a35aa9951d14e06d48cfbf876d8ff67519403a2522b181943b", + "sha256:eed394099a7792834f0cb4a8f615319152b9d801444c1c9e1b1a2c36d2239f9e", + "sha256:f76dbe44e31abf516114f6347a46fa4e7c2e8bceaa4b6f7ee3a0a03c8eba3c17", + "sha256:fc15874816b9320581133ddc2096b644582ab870cf6a6ed63684433e7af4b0d3", + "sha256:fc9fb11b65e7bc49f7f75aaba1b700f7181d95d4e151cf2f24d51bfd14410b77" + ], + "version": "==4.7.1" }, "markuppy": { "hashes": [ @@ -791,31 +791,31 @@ }, "newrelic": { "hashes": [ - "sha256:1cb3ed22ed3c119e557f3a097b2bbcfb6c0aa5aa9842b1fa09d2a8145f4d931a", - "sha256:25fa6091bb6881d9e2918655fe3f1390c080f6f74f9e6607555fb29230836d91", - "sha256:48cac4a9815907df85e9ce287ec9c6172fe4faa57f1750663d8846104d51af78", - "sha256:53835848acb863acc1bc415097156661c7f3c5d483bbfbf9cf19312182fcb797", - "sha256:60c50b17a25128b1400a868304278128ce3d6379acb7b12893efcb5725922e45", - "sha256:8a7f8e46bd02f39d2abb67c39b19a860e8b6ce2263a37ee1fa5744cbfef61f85", - "sha256:9efdb7432457f4cdab03aa417bd1e80974786039c7fddff9fb0c71325e35eea7", - "sha256:a5f3f9e87358bce7ab21789c52d4b16a586b21c6ac70deec2c34c5c87e96fc44", - "sha256:b37e1fa55489a63dd3b76742fc357d02b18ced49ff4efb0da42865beae651956", - "sha256:b85ccfdfef4ca3bb3a25afbbe5281cf2bcdac41e63d5d118e6a1fc405add09ec", - "sha256:c59f76676529e8fb1627333622b9debd3cb825c4f1ee325d1d0249d35bdead0d", - "sha256:e3d59a7d08c32bd386c804057618a2b68b829b2e444c42dddfc0da3eff0eeeb3", - "sha256:ec3d2012c035e846e8c6ca0629decceb3f65eca88e787ab58fc0c56dbf933936", - "sha256:fa5c6a4e8c3feadfc8c246631c631735c91b8f4f0a380add1b629415005b12c0", - "sha256:fee14166041cfdf9743083b4398056d1cd8c727d4df2e3c2090e627ee33e3ddf" - ], - "index": "pypi", - "version": "==7.2.4.171" + "sha256:059915807180f8f240afc7cc6bd243b354a41537f2c41924971d3eabae759b32", + "sha256:0b1d944a2b516f3917dbeb6d03269192cf420d562100237581a45a85b1d442b1", + "sha256:2f82df68486daa53e8781eae93a2353975f211602a5eb19d5046178b16759ad8", + "sha256:47442b6152c886f10fee5fd54cb700d9f702330df2c663276344af3fa5c3ec36", + "sha256:5815878b2edfc40c0544004b09c5ef740e5e344778b836669709b96f1d9090a0", + "sha256:5e8f487035a9d230899123c2390c57d8b3ebcb822de6e868cf6ac6b24944f079", + "sha256:74026271bf49591c0e919516ad5d3ba4728eb3d01f3587091bf8ef1e8f219238", + "sha256:973a3dc1b42b2c5340d97d1285cb25512b287ed87e503bb51ed02cef5a63e601", + "sha256:a5e91b08d2bed02087e5e53da51fe444135cc1c6c4fbd9d708791d731b055c35", + "sha256:a6de1dfb4605a0c975eebd1f5278b6e976c8a804f1ba286b3126ef83473e1c68", + "sha256:afd8c6613ba72e96a2a84bf53dfd3d084078e1f409c156cea8b1c18be152a9c9", + "sha256:cac47d1152ec588614d7eab5ee83a547239b0ea3a2abd65ab2faf9fe1369614f", + "sha256:e7272aaff9efc4b6d9fd0224a836c8b953b84ac0dbcc107041d3bc1ef710b86a", + "sha256:f42c760aad643b700c5d19600baf7d5c1928a036561d2c41ecf80ef7b5842ba3", + "sha256:f72f7d017309dc97b102dfb3826c16e9220e001ebe1ec32329a062b229ba734f" + ], + "index": "pypi", + "version": "==7.4.0.172" }, "oauthlib": { "hashes": [ - "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc", - "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3" + "sha256:23a8208d75b902797ea29fd31fa80a15ed9dc2c6c16fe73f5d346f83f6fa27a2", + "sha256:6db33440354787f9b7f3a6dbd4febf5d0f93758354060e802f6c06cb493022fe" ], - "version": "==3.1.1" + "version": "==3.2.0" }, "odfpy": { "hashes": [ @@ -884,10 +884,10 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6", - "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506" + "sha256:cb7dae7d2c59188c85a1d6c944fad19aded6a26bd9c8ae115a4e1c20eb90b713", + "sha256:f2b6a8067a4fb959d3677d1ed764cc4e63e0f6f565b9a4fc7edc2b18bf80217b" ], - "version": "==3.0.24" + "version": "==3.0.27" }, "psycopg2-binary": { "hashes": [ @@ -985,10 +985,10 @@ }, "python-magic": { "hashes": [ - "sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626", - "sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf" + "sha256:1a2c81e8f395c744536369790bd75094665e9644110a6623bcc3bbea30f03973", + "sha256:21f5f542aa0330f5c8a64442528542f6215c8e18d2466b399b0d9d39356d83fc" ], - "version": "==0.4.24" + "version": "==0.4.25" }, "python3-openid": { "hashes": [ @@ -1048,42 +1048,44 @@ }, "reportlab": { "hashes": [ - "sha256:0c2f479df4eb447ea0757bf60b1ac0d7ddb9980335f4f94975ee6d95bda5b8f8", - "sha256:1055380b2dc73d5143a62451f81b2a739f605dae0e107a764efc0618293837c1", - "sha256:169d7017687c60ddf7690cb349e24ae10d51480d93babc6f81d851aea8a01a25", - "sha256:27ce3e8869c3f22d9d7a8092858649601e76b86e2f3032df39566343b908d929", - "sha256:2efdb2999e1b19a16d5535aa70b5ec5f3ad003e1d366da566f23231ff81400aa", - "sha256:2fa30756c2d5d5e11321114636b0cbeffdf59ffdbcf705b902057ad3801d0d37", - "sha256:3b85b7172b9b4ab0ae74fe0e99d9186ff04104d9158c980391f4e0a54b67f3a8", - "sha256:3d5d9997b91ec7f2d1a2b9928ab20503cf70e8c056b445d0bc7ae29946c13623", - "sha256:50e62429a3487722b4d7621453efc4cbeed80f3b608cad98ef8f06d191a8d0a9", - "sha256:5785aab3b57fe4794147da8908d411c3abf900ac2bc5b0c39782205a1d8c5b51", - "sha256:5d1280c9df17a5d36213b88d66f45a9475005ab39d79b6e9e98893a02a5a033d", - "sha256:68de7f3d3511ea45b9af6e9e4a6b6d89a86d1fe59f41583fb55e6c810ebf23d9", - "sha256:720335d2462ed8ad5ad6ea5da509a9289fab7a78b0cdcdfd56fef5398435119d", - "sha256:7cb6a4ea5cfc08669c0ba66e900cf5c598c33fdb0e3e4ebadf892ff703d594f6", - "sha256:7e51f0195e602c207edcf3a768a6005a10b3db786539b74eb99afe6c9fd5656a", - "sha256:ae3959094b48bdae729e838d84156d31691f0bd17c640b8b10ff0fdbbc11c031", - "sha256:af350308e8b8720ca6db7763b56e96b37976576c1f8b0069764074dc41a19254", - "sha256:b75a4f634e8ba89cc22ff58b9bdfd01a239b2e2fc85d086d1a2d70d08167c443", - "sha256:bb8c380bceb3623f39a96b6bc8cf8db75857fea3f67900391763b5caee23ffa3", - "sha256:be4f05230eb17b9c9c61a180ab0c89c30112da2823c77807a2a5ddba19365865", - "sha256:c166a6c168232948e9b100dcab1b88a4b21efe0aa14c5c18bafd28fffffb4576", - "sha256:c29e7cde992c56687c6f68053dea4aa3beb0d406df28738e95950d88deb38109", - "sha256:c4e0abfa0daf0c48a6bffc46c51b2e5f6272a1d57593c51e7bc855272f763130", - "sha256:c79f89c277f49dfd2829b9a046b20c12cd46fe69f474e4dca349e731a2397021", - "sha256:d35cc6ae73a25b2e75b23e60d3dca0e5153dff97d9e22b28ac82712c79656fd9", - "sha256:d57b5374a44aab9f3898c57ed3c2e6ba159878a2a37f36ddd154adf6f4b3a5c0", - "sha256:d5b56d9912f148cca4fdc0d6c805a56931bb1a4e59e899db92a3531e78f2a9de", - "sha256:d7145d010d561c502e51795adb2e4f7534f28f12e32db0b0694081c6173c8b27", - "sha256:d851fecf4bb6484d4038a402430f30294911aa116686624d1e79b9e3cdb1ed2c", - "sha256:d94a20b7f2aad166ffe74a77bff02d82a82c514dba6d3e431fdb14675db5c383", - "sha256:dcbf4bcf0917cb50964a9c47198e802791eae2581e7788f43da8f50ed5744d8a", - "sha256:e8b214321e2e16209a68a4cdbe3391379845cd0da434362cf3c6d2d1053146fe", - "sha256:f0cc8308678a8136481572463e5ac92a145d2fb487aa22c842347af8a063d50a", - "sha256:f2c0977a39bea423f6a0b53faaabef3b2f8602b1d3e09c57f6952d60ad363119" - ], - "version": "==3.6.3" + "sha256:22c28e593e2c37110f79df9bb31ba7782dc8c0002f33d8070c6d18e1c7380bfc", + "sha256:238f1088b1ce94d25790774546fc52e3efd909eafe0c56f71d286996dd2d2db0", + "sha256:2668687baf0a6c64f90193eca74dfa69bf172bf38e436c7be91e0b13867132ec", + "sha256:2adb9c53c86b30290b407a24b88cf07b09c3b325866b5125b4dca4aa7996021e", + "sha256:2ca0c987433bf63d765a9dcc9cb54695e617725ee81058af615f8d42fc29c0d8", + "sha256:2cf111835bd4b9afbdf8568c4031e2727cdc64a914bbd68e60aa190672f70d34", + "sha256:30d75931893f6c5beb14a93b0a3701cf14a6353c0b48acefa6b4c2391464b861", + "sha256:44c62615504f669a92a62431e847a11c281072ec3a4820a8880dab7338cad53c", + "sha256:473680fb899aed897963ddbf4536b377e40c7ea6fba83337e7f544e3040df956", + "sha256:502ae45775ddf6ed10f23253f8a7768b52b9517ac590babcb92aab0336a2a13a", + "sha256:5a681047247a6d896ed7ec18b95054c9c139c0269417beb066985244b8d18f75", + "sha256:5d62c8341a426984d488fadab2e2b35c4e3e4f5c6ceb2e6b57d7fc41cb7ba992", + "sha256:6910eb0152a72be5ebe8984472f9b2eeb1a5dc3db20a591cbcf179b14c2757a8", + "sha256:6e9f42099141bb35013297b8de8b7329946d94e881cbd72c3d76f44d5a9df705", + "sha256:7ac03370a672c9df9e691da4870f5db79d6227f37a6faf7d17a822890d42de60", + "sha256:8a49fec7ea0c410dc84c88ac8c965605a3e6d50a9b81afb9539175168c7deaf7", + "sha256:97b5ab874e8d74f3dbe3b48a531df7df269acb35c3e5eed9d41b3579bef9ad77", + "sha256:9db71af717229dad72fe5f4dfb587eb952a07f7c1bcd83df402b676c78a334f5", + "sha256:a089addc73b770d159615fc4c90cd06226b0c071d30c63e8addf57b9533049ee", + "sha256:a09acda69357664190a02f239abb01505d519a2563ba89d57d6fb55ca14ade72", + "sha256:ae252b718fb6de4da766d2b4b3402592923e327641dfa0a1b3cfecaa8a95229f", + "sha256:b109d8594a5140f8c0e93c0d091e16c6274267027077cddbc590d4bff7acb35c", + "sha256:b1d4940ff5f573f54855507c2d2ddfeb9a034ad3f040fa5168cf235717531b78", + "sha256:b44a59e75a2c20912e21960df45c0644ded4538300becbb1df5b4cceea2afa11", + "sha256:b84c0c3ad09eb9183fb2e54e44da92d84436d9f3a3263d1456e463c723c54906", + "sha256:d05603fcf2acee5d01eb814d36b212aafbd82cafb9ae861dff41daaf893f95f1", + "sha256:d42a442f4593ab5e196debc32aff0c36fcbf4031f068e1c9435d4137f47d7990", + "sha256:dd1cdb62dc123f5859ca514eb639f70660bdc818c95fb0ee2370a175a0e20ce4", + "sha256:e6d3affa0e484fb55e1061bbdf778797c68a648127f91102b1f0a6173ecb590e", + "sha256:e7ca3699612efc278c666193aa340937066d8045cde247c4b409c8f416e0811e", + "sha256:e80ed55cbbaf905635a2673d439495e1b1925b8379ea56aa2fc859a00e41af9f", + "sha256:edab6b0fc5984051b9b74d33579b7e3d228b70a5801904aa645828a95efb8486", + "sha256:ef659caf2f2824ab0bdf9e98a3886272232bcb1c756be4eb4f5c3c60a9519092", + "sha256:f00e0218854e168bd8d5379d07f0e138285c34b5fe3878c8d5d4f691e280d95e", + "sha256:f2bc48fc45f13d9ccc123462ab3bfd18a78e4bd58d027f9d4a226110c78adc3c", + "sha256:f2be927d8717c5947e7968f089492c088a4103bfe6287ee01a001e0b9a84545b" + ], + "version": "==3.6.6" }, "requests": { "hashes": [ @@ -1095,18 +1097,18 @@ }, "requests-oauthlib": { "hashes": [ - "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", - "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a" + "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", + "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a" ], - "version": "==1.3.0" + "version": "==1.3.1" }, "sentry-sdk": { "hashes": [ - "sha256:0db297ab32e095705c20f742c3a5dac62fe15c4318681884053d0898e5abb2f6", - "sha256:789a11a87ca02491896e121efdd64e8fd93327b69e8f2f7d42f03e2569648e88" + "sha256:4fc7960a82c95d906a0514cf4d9aacba1743eb9863a5b7c2a01c525a7d9b21e6", + "sha256:f7e54567937ebcbe938c4df1075ec891587faeb7c74184b88cf2894e47c86116" ], "index": "pypi", - "version": "==1.5.0" + "version": "==1.5.4" }, "simplejson": { "hashes": [ @@ -1222,10 +1224,10 @@ "yaml" ], "hashes": [ - "sha256:26141c9cf2d5904a2228d3f5d45f8a46a3f3f2f0fbb4c33b4a1c1ddca9f31348", - "sha256:d64c9f6712918a3d90ec5d71b44b8bab1083e3609e4844ad2be80eb633e097ed" + "sha256:12d8686454c721de88d8ca5adf07e1f419ef6dbcecedf65e8950d4a329daf3a0", + "sha256:1ba12da7b0b17e33f5997fb1bc8ed560aae3535f5892ae5e5c01a056c47d4d78" ], - "version": "==3.1.0" + "version": "==3.2.0" }, "tenant-schemas-celery": { "hashes": [ @@ -1299,11 +1301,11 @@ }, "unicef-locations": { "hashes": [ - "sha256:87432b120d10f33746bb8e12f38fedc999ea0043be2d581a96a4632c2ffc0e58", - "sha256:bdd0f3c722d79c1aca41f6866f33a09ea9d126e2a9b12e8fb3524c5d40909a60" + "sha256:7c69221801368ec9a48e05dff1ac19fae17515c7a695790d25ee4e975f7f3731", + "sha256:e54150a1241ee061b12bdce42af59f986caa5dbf32a0a02d18f6e6e39967e31e" ], "index": "pypi", - "version": "==3.1" + "version": "==3.2.1" }, "unicef-notification": { "hashes": [ @@ -1359,10 +1361,10 @@ }, "urllib3": { "hashes": [ - "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece", - "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844" + "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed", + "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c" ], - "version": "==1.26.7" + "version": "==1.26.8" }, "vine": { "hashes": [ @@ -1423,6 +1425,13 @@ "markers": "sys_platform == 'darwin'", "version": "==0.1.2" }, + "asttokens": { + "hashes": [ + "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c", + "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5" + ], + "version": "==2.0.5" + }, "babel": { "hashes": [ "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9", @@ -1437,12 +1446,33 @@ ], "version": "==0.2.0" }, - "backports.entry-points-selectable": { - "hashes": [ - "sha256:7fceed9532a7aa2bd888654a7314f864a3c16a4e710b34a58cfc0f08114c663b", - "sha256:914b21a479fde881635f7af5adc7f6e38d6b274be32269070c53b698c60d5386" - ], - "version": "==1.1.1" + "black": { + "hashes": [ + "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2", + "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71", + "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6", + "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5", + "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912", + "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866", + "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d", + "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0", + "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321", + "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8", + "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd", + "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3", + "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba", + "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0", + "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5", + "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a", + "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28", + "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c", + "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1", + "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab", + "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f", + "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61", + "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3" + ], + "version": "==22.1.0" }, "certifi": { "hashes": [ @@ -1453,71 +1483,72 @@ }, "charset-normalizer": { "hashes": [ - "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721", - "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c" + "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45", + "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c" ], "markers": "python_version >= '3'", - "version": "==2.0.9" + "version": "==2.0.11" + }, + "click": { + "hashes": [ + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" + ], + "version": "==7.1.2" }, "coverage": { "hashes": [ - "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0", - "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd", - "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884", - "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48", - "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76", - "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0", - "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64", - "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685", - "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47", - "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d", - "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840", - "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f", - "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971", - "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c", - "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a", - "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de", - "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17", - "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4", - "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521", - "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57", - "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b", - "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282", - "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644", - "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475", - "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d", - "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da", - "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953", - "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2", - "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e", - "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c", - "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc", - "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64", - "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74", - "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617", - "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3", - "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d", - "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa", - "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739", - "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8", - "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8", - "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781", - "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58", - "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9", - "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c", - "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd", - "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e", - "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49" - ], - "index": "pypi", - "version": "==6.2" + "sha256:1245ab82e8554fa88c4b2ab1e098ae051faac5af829efdcf2ce6b34dccd5567c", + "sha256:1bc6d709939ff262fd1432f03f080c5042dc6508b6e0d3d20e61dd045456a1a0", + "sha256:25e73d4c81efa8ea3785274a2f7f3bfbbeccb6fcba2a0bdd3be9223371c37554", + "sha256:276b13cc085474e482566c477c25ed66a097b44c6e77132f3304ac0b039f83eb", + "sha256:2aed4761809640f02e44e16b8b32c1a5dee5e80ea30a0ff0912158bde9c501f2", + "sha256:2dd70a167843b4b4b2630c0c56f1b586fe965b4f8ac5da05b6690344fd065c6b", + "sha256:352c68e233409c31048a3725c446a9e48bbff36e39db92774d4f2380d630d8f8", + "sha256:3f2b05757c92ad96b33dbf8e8ec8d4ccb9af6ae3c9e9bd141c7cc44d20c6bcba", + "sha256:448d7bde7ceb6c69e08474c2ddbc5b4cd13c9e4aa4a717467f716b5fc938a734", + "sha256:463e52616ea687fd323888e86bf25e864a3cc6335a043fad6bbb037dbf49bbe2", + "sha256:482fb42eea6164894ff82abbcf33d526362de5d1a7ed25af7ecbdddd28fc124f", + "sha256:56c4a409381ddd7bbff134e9756077860d4e8a583d310a6f38a2315b9ce301d0", + "sha256:56d296cbc8254a7dffdd7bcc2eb70be5a233aae7c01856d2d936f5ac4e8ac1f1", + "sha256:5e15d424b8153756b7c903bde6d4610be0c3daca3986173c18dd5c1a1625e4cd", + "sha256:618eeba986cea7f621d8607ee378ecc8c2504b98b3fdc4952b30fe3578304687", + "sha256:61d47a897c1e91f33f177c21de897267b38fbb45f2cd8e22a710bcef1df09ac1", + "sha256:621f6ea7260ea2ffdaec64fe5cb521669984f567b66f62f81445221d4754df4c", + "sha256:6a5cdc3adb4f8bb8d8f5e64c2e9e282bc12980ef055ec6da59db562ee9bdfefa", + "sha256:6c3f6158b02ac403868eea390930ae64e9a9a2a5bbfafefbb920d29258d9f2f8", + "sha256:704f89b87c4f4737da2860695a18c852b78ec7279b24eedacab10b29067d3a38", + "sha256:72128176fea72012063200b7b395ed8a57849282b207321124d7ff14e26988e8", + "sha256:78fbb2be068a13a5d99dce9e1e7d168db880870f7bc73f876152130575bd6167", + "sha256:7bff3a98f63b47464480de1b5bdd80c8fade0ba2832c9381253c9b74c4153c27", + "sha256:84f2436d6742c01136dd940ee158bfc7cf5ced3da7e4c949662b8703b5cd8145", + "sha256:9976fb0a5709988778ac9bc44f3d50fccd989987876dfd7716dee28beed0a9fa", + "sha256:9ad0a117b8dc2061ce9461ea4c1b4799e55edceb236522c5b8f958ce9ed8fa9a", + "sha256:9e3dd806f34de38d4c01416344e98eab2437ac450b3ae39c62a0ede2f8b5e4ed", + "sha256:9eb494070aa060ceba6e4bbf44c1bc5fa97bfb883a0d9b0c9049415f9e944793", + "sha256:9fde6b90889522c220dd56a670102ceef24955d994ff7af2cb786b4ba8fe11e4", + "sha256:9fff3ff052922cb99f9e52f63f985d4f7a54f6b94287463bc66b7cdf3eb41217", + "sha256:a06c358f4aed05fa1099c39decc8022261bb07dfadc127c08cfbd1391b09689e", + "sha256:a4f923b9ab265136e57cc14794a15b9dcea07a9c578609cd5dbbfff28a0d15e6", + "sha256:c5b81fb37db76ebea79aa963b76d96ff854e7662921ce742293463635a87a78d", + "sha256:d5ed164af5c9078596cfc40b078c3b337911190d3faeac830c3f1274f26b8320", + "sha256:d651fde74a4d3122e5562705824507e2f5b2d3d57557f1916c4b27635f8fbe3f", + "sha256:de73fca6fb403dd72d4da517cfc49fcf791f74eee697d3219f6be29adf5af6ce", + "sha256:e647a0be741edbb529a72644e999acb09f2ad60465f80757da183528941ff975", + "sha256:e92c7a5f7d62edff50f60a045dc9542bf939758c95b2fcd686175dd10ce0ed10", + "sha256:eeffd96882d8c06d31b65dddcf51db7c612547babc1c4c5db6a011abe9798525", + "sha256:f5a4551dfd09c3bd12fca8144d47fe7745275adf3229b7223c2f9e29a975ebda", + "sha256:fac0bcc5b7e8169bffa87f0dcc24435446d329cbc2b5486d155c2e0f3b493ae1" + ], + "index": "pypi", + "version": "==6.3.1" }, "decorator": { "hashes": [ - "sha256:7b12e7c3c6ab203a29e157335e9122cb03de9ab7264b137594103fd4a683b374", - "sha256:e59913af105b9860aa2c8d3272d9de5a56a4e608db9a2f167a8480b323d529a7" + "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", + "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" ], - "version": "==5.1.0" + "version": "==5.1.1" }, "distlib": { "hashes": [ @@ -1533,6 +1564,13 @@ ], "version": "==0.17.1" }, + "executing": { + "hashes": [ + "sha256:32fc6077b103bd19e6494a72682d66d5763cf20a106d5aa7c5ccbea4e47b0df7", + "sha256:c23bf42e9a7b9b212f185b1b2c3c91feb895963378887bb10e64a2e612ec0023" + ], + "version": "==0.8.2" + }, "factory-boy": { "hashes": [ "sha256:a98d277b0c047c75eb6e4ab8508a7f81fb03d2cb21986f627913546ef7a2a55e", @@ -1543,10 +1581,10 @@ }, "faker": { "hashes": [ - "sha256:3163c84866cf118ac5329a802e046b0f729528ce62ebb2806b626e0badbb6ff3", - "sha256:530690ad12a2a054071af95fc8a354c5fd57b5e7707053a9662f40f14a87b68e" + "sha256:534c9410cd003b794900504d37f0afaf8275bfe8865583250799f696cf227cd3", + "sha256:820e55f62b428a4d55f6700358167e84a6ba3f8371e9ef39f9ca03a504dcae18" ], - "version": "==10.0.0" + "version": "==12.1.0" }, "fancycompleter": { "hashes": [ @@ -1557,10 +1595,10 @@ }, "filelock": { "hashes": [ - "sha256:2e139a228bcf56dd8b2274a65174d005c4a6b68540ee0bdbb92c76f43f29f7e8", - "sha256:93d512b32a23baf4cac44ffd72ccf70732aeff7b8050fcaf6d3ec406d954baf4" + "sha256:38b4f4c989f9d06d44524df1b24bd19e167d851f19b50bf3e3559952dddc5b80", + "sha256:cf0fc6a2f8d26bd900f19bf33915ca70ba4dd8c56903eeb14e1e7a2fd7590146" ], - "version": "==3.4.0" + "version": "==3.4.2" }, "flake8": { "hashes": [ @@ -1593,13 +1631,21 @@ ], "version": "==1.3.0" }, + "importlib-metadata": { + "hashes": [ + "sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6", + "sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e" + ], + "markers": "python_version < '3.10'", + "version": "==4.10.1" + }, "ipython": { "hashes": [ - "sha256:cb6aef731bf708a7727ab6cde8df87f0281b1427d41e65d62d4b68934fa54e97", - "sha256:fc60ef843e0863dd4e24ab2bb5698f071031332801ecf8d1aeb4fb622056545c" + "sha256:ab564d4521ea8ceaac26c3a2c6e5ddbca15c8848fd5a5cc325f960da88d42974", + "sha256:c503a0dd6ccac9c8c260b211f2dd4479c042b49636b097cc9a0d55fe62dff64c" ], "index": "pypi", - "version": "==7.30.1" + "version": "==8.0.1" }, "isort": { "hashes": [ @@ -1721,80 +1767,74 @@ }, "multidict": { "hashes": [ - "sha256:06560fbdcf22c9387100979e65b26fba0816c162b888cb65b845d3def7a54c9b", - "sha256:067150fad08e6f2dd91a650c7a49ba65085303fcc3decbd64a57dc13a2733031", - "sha256:0a2cbcfbea6dc776782a444db819c8b78afe4db597211298dd8b2222f73e9cd0", - "sha256:0dd1c93edb444b33ba2274b66f63def8a327d607c6c790772f448a53b6ea59ce", - "sha256:0fed465af2e0eb6357ba95795d003ac0bdb546305cc2366b1fc8f0ad67cc3fda", - "sha256:116347c63ba049c1ea56e157fa8aa6edaf5e92925c9b64f3da7769bdfa012858", - "sha256:1b4ac3ba7a97b35a5ccf34f41b5a8642a01d1e55454b699e5e8e7a99b5a3acf5", - "sha256:1c7976cd1c157fa7ba5456ae5d31ccdf1479680dc9b8d8aa28afabc370df42b8", - "sha256:246145bff76cc4b19310f0ad28bd0769b940c2a49fc601b86bfd150cbd72bb22", - "sha256:25cbd39a9029b409167aa0a20d8a17f502d43f2efebfe9e3ac019fe6796c59ac", - "sha256:28e6d883acd8674887d7edc896b91751dc2d8e87fbdca8359591a13872799e4e", - "sha256:2d1d55cdf706ddc62822d394d1df53573d32a7a07d4f099470d3cb9323b721b6", - "sha256:2e77282fd1d677c313ffcaddfec236bf23f273c4fba7cdf198108f5940ae10f5", - "sha256:32fdba7333eb2351fee2596b756d730d62b5827d5e1ab2f84e6cbb287cc67fe0", - "sha256:35591729668a303a02b06e8dba0eb8140c4a1bfd4c4b3209a436a02a5ac1de11", - "sha256:380b868f55f63d048a25931a1632818f90e4be71d2081c2338fcf656d299949a", - "sha256:3822c5894c72e3b35aae9909bef66ec83e44522faf767c0ad39e0e2de11d3b55", - "sha256:38ba256ee9b310da6a1a0f013ef4e422fca30a685bcbec86a969bd520504e341", - "sha256:3bc3b1621b979621cee9f7b09f024ec76ec03cc365e638126a056317470bde1b", - "sha256:3d2d7d1fff8e09d99354c04c3fd5b560fb04639fd45926b34e27cfdec678a704", - "sha256:517d75522b7b18a3385726b54a081afd425d4f41144a5399e5abd97ccafdf36b", - "sha256:5f79c19c6420962eb17c7e48878a03053b7ccd7b69f389d5831c0a4a7f1ac0a1", - "sha256:5f841c4f14331fd1e36cbf3336ed7be2cb2a8f110ce40ea253e5573387db7621", - "sha256:637c1896497ff19e1ee27c1c2c2ddaa9f2d134bbb5e0c52254361ea20486418d", - "sha256:6ee908c070020d682e9b42c8f621e8bb10c767d04416e2ebe44e37d0f44d9ad5", - "sha256:77f0fb7200cc7dedda7a60912f2059086e29ff67cefbc58d2506638c1a9132d7", - "sha256:7878b61c867fb2df7a95e44b316f88d5a3742390c99dfba6c557a21b30180cac", - "sha256:78c106b2b506b4d895ddc801ff509f941119394b89c9115580014127414e6c2d", - "sha256:8b911d74acdc1fe2941e59b4f1a278a330e9c34c6c8ca1ee21264c51ec9b67ef", - "sha256:93de39267c4c676c9ebb2057e98a8138bade0d806aad4d864322eee0803140a0", - "sha256:9416cf11bcd73c861267e88aea71e9fcc35302b3943e45e1dbb4317f91a4b34f", - "sha256:94b117e27efd8e08b4046c57461d5a114d26b40824995a2eb58372b94f9fca02", - "sha256:9815765f9dcda04921ba467957be543423e5ec6a1136135d84f2ae092c50d87b", - "sha256:98ec9aea6223adf46999f22e2c0ab6cf33f5914be604a404f658386a8f1fba37", - "sha256:a37e9a68349f6abe24130846e2f1d2e38f7ddab30b81b754e5a1fde32f782b23", - "sha256:a43616aec0f0d53c411582c451f5d3e1123a68cc7b3475d6f7d97a626f8ff90d", - "sha256:a4771d0d0ac9d9fe9e24e33bed482a13dfc1256d008d101485fe460359476065", - "sha256:a5635bcf1b75f0f6ef3c8a1ad07b500104a971e38d3683167b9454cb6465ac86", - "sha256:a9acb76d5f3dd9421874923da2ed1e76041cb51b9337fd7f507edde1d86535d6", - "sha256:ac42181292099d91217a82e3fa3ce0e0ddf3a74fd891b7c2b347a7f5aa0edded", - "sha256:b227345e4186809d31f22087d0265655114af7cda442ecaf72246275865bebe4", - "sha256:b61f85101ef08cbbc37846ac0e43f027f7844f3fade9b7f6dd087178caedeee7", - "sha256:b70913cbf2e14275013be98a06ef4b412329fe7b4f83d64eb70dce8269ed1e1a", - "sha256:b9aad49466b8d828b96b9e3630006234879c8d3e2b0a9d99219b3121bc5cdb17", - "sha256:baf1856fab8212bf35230c019cde7c641887e3fc08cadd39d32a421a30151ea3", - "sha256:bd6c9c50bf2ad3f0448edaa1a3b55b2e6866ef8feca5d8dbec10ec7c94371d21", - "sha256:c1ff762e2ee126e6f1258650ac641e2b8e1f3d927a925aafcfde943b77a36d24", - "sha256:c30ac9f562106cd9e8071c23949a067b10211917fdcb75b4718cf5775356a940", - "sha256:c9631c642e08b9fff1c6255487e62971d8b8e821808ddd013d8ac058087591ac", - "sha256:cdd68778f96216596218b4e8882944d24a634d984ee1a5a049b300377878fa7c", - "sha256:ce8cacda0b679ebc25624d5de66c705bc53dcc7c6f02a7fb0f3ca5e227d80422", - "sha256:cfde464ca4af42a629648c0b0d79b8f295cf5b695412451716531d6916461628", - "sha256:d3def943bfd5f1c47d51fd324df1e806d8da1f8e105cc7f1c76a1daf0f7e17b0", - "sha256:d9b668c065968c5979fe6b6fa6760bb6ab9aeb94b75b73c0a9c1acf6393ac3bf", - "sha256:da7d57ea65744d249427793c042094c4016789eb2562576fb831870f9c878d9e", - "sha256:dc3a866cf6c13d59a01878cd806f219340f3e82eed514485e094321f24900677", - "sha256:df23c83398715b26ab09574217ca21e14694917a0c857e356fd39e1c64f8283f", - "sha256:dfc924a7e946dd3c6360e50e8f750d51e3ef5395c95dc054bc9eab0f70df4f9c", - "sha256:e4a67f1080123de76e4e97a18d10350df6a7182e243312426d508712e99988d4", - "sha256:e5283c0a00f48e8cafcecadebfa0ed1dac8b39e295c7248c44c665c16dc1138b", - "sha256:e58a9b5cc96e014ddf93c2227cbdeca94b56a7eb77300205d6e4001805391747", - "sha256:e6453f3cbeb78440747096f239d282cc57a2997a16b5197c9bc839099e1633d0", - "sha256:e6c4fa1ec16e01e292315ba76eb1d012c025b99d22896bd14a66628b245e3e01", - "sha256:e7d81ce5744757d2f05fc41896e3b2ae0458464b14b5a2c1e87a6a9d69aefaa8", - "sha256:ea21d4d5104b4f840b91d9dc8cbc832aba9612121eaba503e54eaab1ad140eb9", - "sha256:ecc99bce8ee42dcad15848c7885197d26841cb24fa2ee6e89d23b8993c871c64", - "sha256:f0bb0973f42ffcb5e3537548e0767079420aefd94ba990b61cf7bb8d47f4916d", - "sha256:f19001e790013ed580abfde2a4465388950728861b52f0da73e8e8a9418533c0", - "sha256:f76440e480c3b2ca7f843ff8a48dc82446b86ed4930552d736c0bac507498a52", - "sha256:f9bef5cff994ca3026fcc90680e326d1a19df9841c5e3d224076407cc21471a1", - "sha256:fc66d4016f6e50ed36fb39cd287a3878ffcebfa90008535c62e0e90a7ab713ae", - "sha256:fd77c8f3cba815aa69cb97ee2b2ef385c7c12ada9c734b0f3b32e26bb88bbf1d" - ], - "version": "==5.2.0" + "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60", + "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c", + "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672", + "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51", + "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032", + "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2", + "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b", + "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80", + "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88", + "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a", + "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d", + "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389", + "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c", + "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9", + "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c", + "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516", + "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b", + "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43", + "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee", + "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227", + "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d", + "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae", + "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7", + "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4", + "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9", + "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f", + "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013", + "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9", + "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e", + "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693", + "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a", + "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15", + "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb", + "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96", + "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87", + "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376", + "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658", + "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0", + "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071", + "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360", + "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc", + "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3", + "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba", + "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8", + "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9", + "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2", + "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3", + "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68", + "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8", + "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d", + "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49", + "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608", + "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57", + "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86", + "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20", + "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293", + "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849", + "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937", + "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d" + ], + "version": "==6.0.2" + }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" }, "packaging": { "hashes": [ @@ -1810,6 +1850,13 @@ ], "version": "==0.8.3" }, + "pathspec": { + "hashes": [ + "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", + "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" + ], + "version": "==0.9.0" + }, "pdbpp": { "hashes": [ "sha256:79580568e33eb3d6f6b462b1187f53e10cd8e4538f7d31495c9181e2cf9665d1", @@ -1835,10 +1882,10 @@ }, "platformdirs": { "hashes": [ - "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2", - "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d" + "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca", + "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda" ], - "version": "==2.4.0" + "version": "==2.4.1" }, "pluggy": { "hashes": [ @@ -1849,10 +1896,10 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6", - "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506" + "sha256:cb7dae7d2c59188c85a1d6c944fad19aded6a26bd9c8ae115a4e1c20eb90b713", + "sha256:f2b6a8067a4fb959d3677d1ed764cc4e63e0f6f565b9a4fc7edc2b18bf80217b" ], - "version": "==3.0.24" + "version": "==3.0.27" }, "ptyprocess": { "hashes": [ @@ -1861,6 +1908,13 @@ ], "version": "==0.7.0" }, + "pure-eval": { + "hashes": [ + "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", + "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" + ], + "version": "==0.2.2" + }, "py": { "hashes": [ "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", @@ -1884,17 +1938,17 @@ }, "pygments": { "hashes": [ - "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380", - "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6" + "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65", + "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a" ], - "version": "==2.10.0" + "version": "==2.11.2" }, "pyparsing": { "hashes": [ - "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4", - "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81" + "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea", + "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484" ], - "version": "==3.0.6" + "version": "==3.0.7" }, "pyrepl": { "hashes": [ @@ -1961,11 +2015,11 @@ }, "responses": { "hashes": [ - "sha256:a2e3aca2a8277e61257cd3b1c154b1dd0d782b1ae3d38b7fa37cbe3feb531791", - "sha256:f358ef75e8bf431b0aa203cc62625c3a1c80a600dbe9de91b944bf4e9c600b92" + "sha256:15c63ad16de13ee8e7182d99c9334f64fd81f1ee79f90748d527c28f7ca9dd51", + "sha256:380cad4c1c1dc942e5e8a8eaae0b4d4edf708f4f010db8b7bcfafad1fcd254ff" ], "index": "pypi", - "version": "==0.16.0" + "version": "==0.18.0" }, "six": { "hashes": [ @@ -1983,11 +2037,11 @@ }, "sphinx": { "hashes": [ - "sha256:048dac56039a5713f47a554589dc98a442b39226a2b9ed7f82797fcb2fe9253f", - "sha256:32a5b3e9a1b176cc25ed048557d4d3d01af635e6b76c5bc7a43b0a34447fbd45" + "sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe", + "sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc" ], "index": "pypi", - "version": "==4.3.1" + "version": "==4.4.0" }, "sphinxcontrib-applehelp": { "hashes": [ @@ -2031,12 +2085,12 @@ ], "version": "==1.1.5" }, - "text-unidecode": { + "stack-data": { "hashes": [ - "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", - "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" + "sha256:02cc0683cbc445ae4ca8c4e3a0e58cb1df59f252efb0aa016b34804a707cf9bc", + "sha256:7769ed2482ce0030e00175dd1bf4ef1e873603b6ab61cd3da443b410e64e9477" ], - "version": "==1.3" + "version": "==0.1.4" }, "toml": { "hashes": [ @@ -2045,13 +2099,20 @@ ], "version": "==0.10.2" }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "version": "==2.0.1" + }, "tox": { "hashes": [ - "sha256:5e274227a53dc9ef856767c21867377ba395992549f02ce55eb549f9fb9a8d10", - "sha256:c30b57fa2477f1fb7c36aa1d83292d5c2336cd0018119e1b1c17340e2c2708ca" + "sha256:67e0e32c90e278251fea45b696d0fef3879089ccbe979b0c556d35d5a70e2993", + "sha256:be3362472a33094bce26727f5f771ca0facf6dafa217f65875314e9a6600c95c" ], "index": "pypi", - "version": "==3.24.4" + "version": "==3.24.5" }, "traitlets": { "hashes": [ @@ -2060,12 +2121,20 @@ ], "version": "==5.1.1" }, + "typing-extensions": { + "hashes": [ + "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e", + "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b" + ], + "markers": "python_version < '3.10'", + "version": "==4.0.1" + }, "urllib3": { "hashes": [ - "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece", - "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844" + "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed", + "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c" ], - "version": "==1.26.7" + "version": "==1.26.8" }, "vcrpy": { "hashes": [ @@ -2077,10 +2146,10 @@ }, "virtualenv": { "hashes": [ - "sha256:4b02e52a624336eece99c96e3ab7111f469c24ba226a53ec474e8e787b365814", - "sha256:576d05b46eace16a9c348085f7d0dc8ef28713a2cabaa1cf0aea41e8f12c9218" + "sha256:45e1d053cad4cd453181ae877c4ffc053546ae99e7dd049b9ff1d9be7491abf7", + "sha256:e0621bcbf4160e4e1030f05065c8834b4e93f4fcc223255db2a823440aca9c14" ], - "version": "==20.10.0" + "version": "==20.13.1" }, "wcwidth": { "hashes": [ @@ -2228,6 +2297,13 @@ ], "markers": "python_version >= '3.6'", "version": "==1.7.2" + }, + "zipp": { + "hashes": [ + "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d", + "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375" + ], + "version": "==3.7.0" } } } diff --git a/src/etools/applications/field_monitoring/analyze/tests/test_views.py b/src/etools/applications/field_monitoring/analyze/tests/test_views.py index 1454f8bc41..2af6550174 100644 --- a/src/etools/applications/field_monitoring/analyze/tests/test_views.py +++ b/src/etools/applications/field_monitoring/analyze/tests/test_views.py @@ -193,7 +193,7 @@ def setUpTestData(cls): super().setUpTestData() cls.user = UserFactory(unicef_user=True) - cls.country = LocationFactory(gateway__admin_level=0) + cls.country = LocationFactory(admin_level=0) cls.first_location = LocationFactory(parent=cls.country) cls.second_location = LocationFactory(parent=cls.country) LocationFactory(parent=cls.first_location) # hidden diff --git a/src/etools/applications/field_monitoring/analyze/views.py b/src/etools/applications/field_monitoring/analyze/views.py index 564ef6998c..591eaa1308 100644 --- a/src/etools/applications/field_monitoring/analyze/views.py +++ b/src/etools/applications/field_monitoring/analyze/views.py @@ -83,7 +83,7 @@ class CoverageCPOutputsView(ListAPIView): class CoverageGeographicView(ListAPIView): serializer_class = CoverageGeographicSerializer - queryset = Location.objects.filter(parent__gateway__admin_level=0) + queryset = Location.objects.filter(parent__admin_level=0) def get_queryset(self): queryset = super().get_queryset() diff --git a/src/etools/applications/field_monitoring/fm_settings/export/serializers.py b/src/etools/applications/field_monitoring/fm_settings/export/serializers.py index bd35431caf..ec6caf2436 100644 --- a/src/etools/applications/field_monitoring/fm_settings/export/serializers.py +++ b/src/etools/applications/field_monitoring/fm_settings/export/serializers.py @@ -26,7 +26,7 @@ def get_parents_info(self, obj): level = i + 1 parents_info.update({ 'admin_{}_name'.format(level): parent.name if parent else '', - 'admin_{}_type'.format(level): parent.gateway.name if parent else '', + 'admin_{}_type'.format(level): parent.admin_level_name if parent else '', 'admin_{}_pcode'.format(level): parent.p_code if parent else '', }) diff --git a/src/etools/applications/field_monitoring/fm_settings/models.py b/src/etools/applications/field_monitoring/fm_settings/models.py index 420a9791cc..84a67ccb88 100644 --- a/src/etools/applications/field_monitoring/fm_settings/models.py +++ b/src/etools/applications/field_monitoring/fm_settings/models.py @@ -208,7 +208,7 @@ def get_parent_location(point): matched_locations = list(filter(lambda l: l.is_leaf_node(), locations)) or locations location = min(matched_locations, key=lambda l: l.geom.length) else: - location = Location.objects.filter(gateway__admin_level=0, is_active=True).first() + location = Location.objects.filter(admin_level=0, is_active=True).first() return location diff --git a/src/etools/applications/field_monitoring/fm_settings/tests/factories.py b/src/etools/applications/field_monitoring/fm_settings/tests/factories.py index a53a124fda..62404159b8 100644 --- a/src/etools/applications/field_monitoring/fm_settings/tests/factories.py +++ b/src/etools/applications/field_monitoring/fm_settings/tests/factories.py @@ -2,7 +2,6 @@ import factory from factory import fuzzy, LazyAttribute -from unicef_locations.models import GatewayType from unicef_locations.tests.factories import LocationFactory from etools.applications.attachments.tests.factories import AttachmentFactory @@ -29,8 +28,7 @@ class LocationSiteFactory(factory.django.DjangoModelFactory): name = factory.Sequence(lambda n: 'Location {}'.format(n)) point = GEOSGeometry("POINT(20 20)") p_code = factory.Sequence(lambda n: 'PCODE{}'.format(n)) - parent = factory.LazyFunction(lambda: - LocationFactory(gateway=GatewayType.objects.get_or_create(admin_level=0)[0])) + parent = factory.LazyFunction(lambda: LocationFactory(admin_level=0)) class Meta: model = LocationSite diff --git a/src/etools/applications/field_monitoring/fm_settings/tests/test_models.py b/src/etools/applications/field_monitoring/fm_settings/tests/test_models.py index a0cbc31e81..dab62e50f2 100644 --- a/src/etools/applications/field_monitoring/fm_settings/tests/test_models.py +++ b/src/etools/applications/field_monitoring/fm_settings/tests/test_models.py @@ -65,7 +65,7 @@ def setUpTestData(cls): } """ ) - cls.country = LocationFactory(gateway__admin_level=0) + cls.country = LocationFactory(admin_level=0) cls.boundary_location = LocationFactory(geom=cls.boundary) def test_parent_boundary(self): diff --git a/src/etools/applications/field_monitoring/fm_settings/tests/test_views.py b/src/etools/applications/field_monitoring/fm_settings/tests/test_views.py index 2b42ae49b8..d06e805bf5 100644 --- a/src/etools/applications/field_monitoring/fm_settings/tests/test_views.py +++ b/src/etools/applications/field_monitoring/fm_settings/tests/test_views.py @@ -6,7 +6,6 @@ from factory import fuzzy from rest_framework import status from unicef_attachments.models import Attachment, AttachmentLink, FileType -from unicef_locations.models import GatewayType from unicef_locations.tests.factories import LocationFactory from etools.applications.attachments.tests.factories import ( @@ -81,7 +80,7 @@ def setUpTestData(cls): """ ) - cls.country = LocationFactory(gateway__admin_level=0, geom=boundary) + cls.country = LocationFactory(admin_level=0, geom=boundary) cls.child_location = LocationFactory(parent=cls.country, geom=boundary) def test_filter_root(self): @@ -278,10 +277,8 @@ def test_destroy_unicef(self): self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_csv_export(self): - gateway_0, _created = GatewayType.objects.get_or_create(admin_level=0, defaults={'name': 'Gateway level 0'}) - gateway_1, _created = GatewayType.objects.get_or_create(admin_level=1, defaults={'name': 'Gateway level 1'}) - LocationSiteFactory(point=GEOSGeometry("POINT(1 2)"), parent__gateway=gateway_0) - LocationSiteFactory(parent__gateway=gateway_1, parent__parent__gateway=gateway_0) + LocationSiteFactory(point=GEOSGeometry("POINT(1 2)"), parent__admin_level=0) + LocationSiteFactory(parent__admin_level=1, parent__parent__admin_level=0) response = self._test_export(self.unicef_user, 'field_monitoring_settings:sites-export') @@ -295,11 +292,8 @@ def test_csv_export_no_sites(self): class LocationsCountryViewTestCase(FMBaseTestCaseMixin, BaseTenantTestCase): def test_retrieve(self): - country = LocationFactory( - gateway__admin_level=0, - point="POINT(20 20)", - ) - LocationFactory(gateway__admin_level=1) + country = LocationFactory(admin_level=0, point="POINT(20 20)") + LocationFactory(admin_level=1) response = self.forced_auth_req( 'get', reverse('field_monitoring_settings:locations-country'), @@ -311,10 +305,8 @@ def test_retrieve(self): self.assertEqual(response.data['point']['type'], 'Point') def test_centroid(self): - LocationFactory( - gateway__admin_level=0, - ) - LocationFactory(gateway__admin_level=1, point="POINT(20 20)",) + LocationFactory(admin_level=0) + LocationFactory(admin_level=1, point="POINT(20 20)",) response = self.forced_auth_req( 'get', reverse('field_monitoring_settings:locations-country'), diff --git a/src/etools/applications/field_monitoring/fm_settings/views.py b/src/etools/applications/field_monitoring/fm_settings/views.py index c9a8a46b55..2d5f6a19d0 100644 --- a/src/etools/applications/field_monitoring/fm_settings/views.py +++ b/src/etools/applications/field_monitoring/fm_settings/views.py @@ -98,7 +98,7 @@ class LocationSitesViewSet(FMBaseViewSet, viewsets.ModelViewSet): filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter) filter_fields = ('is_active',) ordering_fields = ( - 'parent__gateway__admin_level', 'parent__name', + 'parent__admin_level', 'parent__name', 'is_active', 'name', ) search_fields = ('parent__name', 'parent__p_code', 'name', 'p_code') @@ -128,7 +128,7 @@ def export(self, request, *args, **kwargs): class LocationsCountryView(views.APIView): def get(self, request, *args, **kwargs): - country = get_object_or_404(Location, gateway__admin_level=0, is_active=True) + country = get_object_or_404(Location, admin_level=0, is_active=True) return Response(data=LocationFullSerializer(instance=country).data) @@ -137,7 +137,7 @@ class FMLocationsViewSet(FMBaseViewSet, mixins.ListModelMixin, viewsets.GenericV serializer_class = LocationFullSerializer filter_backends = (DjangoFilterBackend, SearchFilter) filter_fields = ('level', 'parent') - search_fields = ('name', 'gateway__name') + search_fields = ('name', 'admin_level_name') @action(methods=['get'], detail=True) def path(self, request, *args, **kwargs): diff --git a/src/etools/applications/field_monitoring/planning/views.py b/src/etools/applications/field_monitoring/planning/views.py index 8562cd1b59..d94492a4ff 100644 --- a/src/etools/applications/field_monitoring/planning/views.py +++ b/src/etools/applications/field_monitoring/planning/views.py @@ -142,7 +142,7 @@ class MonitoringActivitiesViewSet( Retrieve and Update Agreement. """ queryset = MonitoringActivity.objects.annotate(checklists_count=Count('checklists')).select_related( - 'tpm_partner', 'visit_lead', 'location__gateway', 'location_site', + 'tpm_partner', 'visit_lead', 'location', 'location_site', ).prefetch_related( 'team_members', 'partners', 'interventions', 'cp_outputs' ).order_by("-id") diff --git a/src/etools/applications/management/serializers.py b/src/etools/applications/management/serializers.py index 4c31f2ee9d..0cd10dbcb5 100644 --- a/src/etools/applications/management/serializers.py +++ b/src/etools/applications/management/serializers.py @@ -15,7 +15,6 @@ class Meta: 'parent_id', 'name', 'p_code', - 'gateway_id', 'level', ) @@ -39,7 +38,6 @@ class Meta: 'parent_id', 'name', 'p_code', - 'gateway_id', 'level', 'geom', 'point' @@ -57,7 +55,6 @@ class Meta: 'parent_id', 'name', 'p_code', - 'gateway_id', 'level', 'geom', 'point' diff --git a/src/etools/applications/management/tests/test_views.py b/src/etools/applications/management/tests/test_views.py index 77fdc5d29b..18a3f9e9fe 100644 --- a/src/etools/applications/management/tests/test_views.py +++ b/src/etools/applications/management/tests/test_views.py @@ -274,7 +274,7 @@ def test_travel_locations_in_use(self): ) self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(sorted(response.data[0].keys()), ["gateway_id", "id", "level", "name", "p_code", "parent_id"]) + self.assertEqual(sorted(response.data[0].keys()), ["id", "level", "name", "p_code", "parent_id"]) def test_intervention_locations_in_use(self): # add intervention locations and test the response @@ -290,7 +290,7 @@ def test_intervention_locations_in_use(self): ) self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(sorted(response.data[0].keys()), ["gateway_id", "id", "level", "name", "p_code", "parent_id"]) + self.assertEqual(sorted(response.data[0].keys()), ["id", "level", "name", "p_code", "parent_id"]) def test_activities_in_use(self): activity = Activity( @@ -309,7 +309,7 @@ def test_activities_in_use(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 2) - self.assertEqual(sorted(response.data[0].keys()), ["gateway_id", "id", "level", "name", "p_code", "parent_id"]) + self.assertEqual(sorted(response.data[0].keys()), ["id", "level", "name", "p_code", "parent_id"]) def test_action_points_in_use(self): ActionPointFactory( @@ -325,7 +325,7 @@ def test_action_points_in_use(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) - self.assertEqual(sorted(response.data[0].keys()), ["gateway_id", "id", "level", "name", "p_code", "parent_id"]) + self.assertEqual(sorted(response.data[0].keys()), ["id", "level", "name", "p_code", "parent_id"]) def test_intervention_locations_geom_bad_request(self): url = reverse("management_gis:locations-gis-geom-list") @@ -414,7 +414,7 @@ def test_intervention_locations_geom_wkt(self): self.assertEqual(len(response.data), 1) self.assertEqual( sorted(response.data[0].keys()), - ["gateway_id", "geom", "id", "level", "name", "p_code", "parent_id", "point"] + ["geom", "id", "level", "name", "p_code", "parent_id", "point"] ) self.assertEqual(response.data[0]["geom"], self.location_with_geom.geom.wkt) @@ -436,7 +436,7 @@ def test_intervention_locations_geom_by_pcode(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( sorted(response.data.keys()), - ["gateway_id", "geom", "id", "level", "name", "p_code", "parent_id", "point"] + ["geom", "id", "level", "name", "p_code", "parent_id", "point"] ) self.assertEqual(response.data["id"], str(self.location_with_geom.id)) self.assertEqual(response.data["geom"], self.location_with_geom.geom.wkt) @@ -473,7 +473,7 @@ def test_intervention_locations_geom_by_id(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( sorted(response.data.keys()), - ["gateway_id", "geom", "id", "level", "name", "p_code", "parent_id", "point"] + ["geom", "id", "level", "name", "p_code", "parent_id", "point"] ) self.assertEqual(response.data["id"], str(self.location_with_geom.id)) self.assertEqual(response.data["geom"], self.location_with_geom.geom.wkt) diff --git a/src/etools/applications/partners/serializers/interventions_v2.py b/src/etools/applications/partners/serializers/interventions_v2.py index 27962d8b0f..abe033958d 100644 --- a/src/etools/applications/partners/serializers/interventions_v2.py +++ b/src/etools/applications/partners/serializers/interventions_v2.py @@ -664,7 +664,7 @@ def get_locations(self, obj): def get_location_names(self, obj): return ['{} [{} - {}]'.format( loc.name, - loc.gateway.name, + loc.admin_level_name, loc.p_code ) for loc in obj.flat_locations.all()] diff --git a/src/etools/applications/partners/serializers/prp_v1.py b/src/etools/applications/partners/serializers/prp_v1.py index 86b244b837..54d1e0136d 100644 --- a/src/etools/applications/partners/serializers/prp_v1.py +++ b/src/etools/applications/partners/serializers/prp_v1.py @@ -104,14 +104,11 @@ class Meta: class PRPLocationSerializer(serializers.ModelSerializer): - pcode = serializers.CharField(source='p_code', read_only=True) - location_type = serializers.CharField(source='gateway.name', read_only=True) - admin_level = serializers.IntegerField(source='gateway.admin_level') class Meta: model = Location depth = 1 - fields = ('id', 'name', 'pcode', 'location_type', 'admin_level') + fields = ('id', 'name', 'p_code', 'admin_level_name', 'admin_level') class DisaggregationValueSerilizer(serializers.ModelSerializer): @@ -164,13 +161,13 @@ def get_locations(self, obj): "id", "name", "p_code", - "gateway__name", - "gateway__admin_level", + "admin_level_name", + "admin_level", ) for loc in location_qs: loc["pcode"] = loc.pop("p_code") - loc["location_type"] = loc.pop("gateway__name") - loc["admin_level"] = loc.pop("gateway__admin_level") + loc["admin_level_name"] = loc.pop("admin_level_name") + loc["admin_level"] = loc.pop("admin_level") return list(location_qs) class Meta: diff --git a/src/etools/applications/partners/tests/data/prp-intervention-list.json b/src/etools/applications/partners/tests/data/prp-intervention-list.json index 505869f7b1..f479171130 100644 --- a/src/etools/applications/partners/tests/data/prp-intervention-list.json +++ b/src/etools/applications/partners/tests/data/prp-intervention-list.json @@ -23,7 +23,7 @@ "admin_level": 0, "pcode": "a-p-code", "name": "A Location", - "location_type": "A Gateway" + "admin_level_name": "A Gateway" } ], "cluster_indicator_id": null, diff --git a/src/etools/applications/partners/tests/test_api_pmp.py b/src/etools/applications/partners/tests/test_api_pmp.py index e7502210f7..7f7c852bde 100644 --- a/src/etools/applications/partners/tests/test_api_pmp.py +++ b/src/etools/applications/partners/tests/test_api_pmp.py @@ -7,7 +7,7 @@ from django_tenants.test.client import TenantClient from rest_framework import status from unicef_djangolib.fields import CURRENCY_LIST -from unicef_locations.tests.factories import GatewayTypeFactory +from unicef_locations.tests.factories import LocationFactory from etools.applications.core.tests.cases import BaseTenantTestCase from etools.applications.core.tests.mixins import URLAssertionMixin @@ -184,15 +184,15 @@ def test_intervention_amendment_types(self): def test_location_types(self): """Verify the location_types portion of the response""" - gateway_types = [GatewayTypeFactory() for i in range(3)] + gateway_types = [LocationFactory() for i in range(3)] response = self.forced_auth_req('get', self.url) d = self._assertResponseFundamentals(response) # These are formatted differently than most other elements in the response. - gateway_types = [{name: getattr(gateway_type, name) for name in ('id', 'name', 'admin_level')} + gateway_types = [{name: getattr(gateway_type, name) for name in ('admin_level', 'admin_level_name')} for gateway_type in gateway_types] - gateway_types.sort(key=lambda gateway_type: gateway_type['id']) + gateway_types.sort(key=lambda gateway_type: gateway_type['admin_level']) self.assertCountEqual(d['location_types'], gateway_types) def test_currencies(self): diff --git a/src/etools/applications/partners/tests/test_api_prp.py b/src/etools/applications/partners/tests/test_api_prp.py index 4f80350323..5f46bd2119 100644 --- a/src/etools/applications/partners/tests/test_api_prp.py +++ b/src/etools/applications/partners/tests/test_api_prp.py @@ -7,7 +7,7 @@ from rest_framework import status from rest_framework.test import APIRequestFactory -from unicef_locations.tests.factories import GatewayTypeFactory, LocationFactory +from unicef_locations.tests.factories import LocationFactory from etools.applications.core.tests.cases import BaseTenantTestCase from etools.applications.core.tests.mixins import WorkspaceRequiredAPITestMixIn @@ -83,6 +83,7 @@ def test_prp_api(self): del expected_intervention['expected_results'][j]['indicators'][0]['blueprint_id'] del expected_intervention['expected_results'][j]['indicators'][0]['disaggregation'][0]['id'] del expected_intervention['expected_results'][j]['indicators'][0]['locations'][0]['id'] + del expected_intervention['expected_results'][j]['indicators'][0]['locations'][0]['admin_level_name'] del expected_intervention['expected_results'][j]['indicators'][0]['locations'][0]['admin_level'] del actual_intervention['expected_results'][j]['id'] @@ -92,6 +93,7 @@ def test_prp_api(self): del actual_intervention['expected_results'][j]['indicators'][0]['blueprint_id'] del actual_intervention['expected_results'][j]['indicators'][0]['disaggregation'][0]['id'] del actual_intervention['expected_results'][j]['indicators'][0]['locations'][0]['id'] + del actual_intervention['expected_results'][j]['indicators'][0]['locations'][0]['admin_level_name'] del actual_intervention['expected_results'][j]['indicators'][0]['locations'][0]['admin_level'] self.assertEqual(response, expected_interventions) @@ -140,9 +142,7 @@ def test_prp_api_performance(self): indicator=indicator_blueprint, lower_result=lower_result, ) - applied_indicator.locations.add(LocationFactory(name='A Location', - gateway=GatewayTypeFactory(name='Another Gateway'), - p_code='a-p-code')) + applied_indicator.locations.add(LocationFactory(name='A Location', p_code='a p-code')) applied_indicator.disaggregation.create(name='Another Disaggregation') with self.assertNumQueries(EXPECTED_QUERIES): self.run_prp_v1( diff --git a/src/etools/applications/partners/tests/test_utils.py b/src/etools/applications/partners/tests/test_utils.py index 73153d795c..460381427e 100644 --- a/src/etools/applications/partners/tests/test_utils.py +++ b/src/etools/applications/partners/tests/test_utils.py @@ -5,7 +5,7 @@ from django.utils import timezone from mock import Mock, patch -from unicef_locations.tests.factories import GatewayTypeFactory, LocationFactory +from unicef_locations.tests.factories import LocationFactory from etools.applications.attachments.tests.factories import AttachmentFileTypeFactory from etools.applications.core.tests.cases import BaseTenantTestCase @@ -89,7 +89,6 @@ def setup_intervention_test_data(test_case, include_results_and_indicators=False ) test_case.applied_indicator.locations.add(LocationFactory( name='A Location', - gateway=GatewayTypeFactory(name='A Gateway'), p_code='a-p-code') ) test_case.disaggregation = test_case.applied_indicator.disaggregation.create(name='A Disaggregation') diff --git a/src/etools/applications/partners/views/v2.py b/src/etools/applications/partners/views/v2.py index 2f481da4fa..974f01ff40 100644 --- a/src/etools/applications/partners/views/v2.py +++ b/src/etools/applications/partners/views/v2.py @@ -13,7 +13,7 @@ from rest_framework.views import APIView from unicef_attachments.models import FileType as AttachmentFileType from unicef_djangolib.fields import CURRENCIES -from unicef_locations.models import GatewayType +from unicef_locations.models import Location from etools.applications.attachments.models import AttachmentFlat from etools.applications.funds.models import FundsReservationItem @@ -93,7 +93,7 @@ def get(self, request): intervention_doc_type = choices_to_json_ready(Intervention.INTERVENTION_TYPES) intervention_status = choices_to_json_ready(Intervention.INTERVENTION_STATUS, sort_choices=False) intervention_amendment_types = choices_to_json_ready(InterventionAmendment.AMENDMENT_TYPES) - location_types = GatewayType.objects.values('id', 'name', 'admin_level').order_by('id') + location_types = Location.objects.values('admin_level_name', 'admin_level').order_by('admin_level').distinct() currencies = choices_to_json_ready(CURRENCIES) attachment_types = AttachmentFileType.objects.values_list( "label", diff --git a/src/etools/applications/users/tests/test_admin.py b/src/etools/applications/users/tests/test_admin.py index 929a500855..758f89dee2 100644 --- a/src/etools/applications/users/tests/test_admin.py +++ b/src/etools/applications/users/tests/test_admin.py @@ -153,7 +153,7 @@ def test_update_hact_button_on_change_page(self): country = Country.objects.exclude(schema_name='public').first() url = reverse('admin:users_country_change', args=[country.pk]) response = self.client.get(url) - self.assertContains(response, text=">Update Hact<", msg_prefix=response.content.decode('utf-8')) + self.assertContains(response, text="Update Hact<", msg_prefix=response.content.decode('utf-8')) self.assertTemplateUsed('admin/users/country/change_form.html') def test_update_hact_action_nonpublic_country(self): diff --git a/src/etools/config/settings/base.py b/src/etools/config/settings/base.py index ba457ce10e..2776ba0d62 100644 --- a/src/etools/config/settings/base.py +++ b/src/etools/config/settings/base.py @@ -572,3 +572,5 @@ def before_send(event, hint): ETOOLS_OFFLINE_API = get_from_secrets_or_env('ETOOLS_OFFLINE_API', '') ETOOLS_OFFLINE_TOKEN = get_from_secrets_or_env('ETOOLS_OFFLINE_TOKEN', '') ETOOLS_OFFLINE_TASK_APP = "etools.config.celery.get_task_app" + +UNICEF_LOCATIONS_MODEL = 'locations.Location' diff --git a/src/etools/config/urls.py b/src/etools/config/urls.py index e92a3f5bc0..75e5d612ea 100644 --- a/src/etools/config/urls.py +++ b/src/etools/config/urls.py @@ -29,7 +29,6 @@ LocationQuerySetView, LocationsLightViewSet, LocationsViewSet, - LocationTypesViewSet, ) # ****************** API docs and schemas ****************************** @@ -59,7 +58,6 @@ api.register(r'locations', LocationsViewSet, basename='locations') api.register(r'locations-light', LocationsLightViewSet, basename='locations-light') -api.register(r'locations-types', LocationTypesViewSet, basename='locationtypes') urlpatterns = [ # Used for admin and dashboard pages in django diff --git a/src/etools/libraries/locations/admin.py b/src/etools/libraries/locations/admin.py index 7d9acf1649..b95cb45c7b 100644 --- a/src/etools/libraries/locations/admin.py +++ b/src/etools/libraries/locations/admin.py @@ -4,7 +4,7 @@ from admin_extra_urls.decorators import button from celery import chain from unicef_locations.admin import CartoDBTableAdmin -from unicef_locations.models import CartoDBTable, LocationRemapHistory +from unicef_locations.models import CartoDBTable from etools.libraries.locations.tasks import import_locations, notify_import_site_completed @@ -41,4 +41,3 @@ def new_id(self, obj): admin.site.unregister(CartoDBTable) admin.site.register(CartoDBTable, EtoolsCartoDBTableAdmin) -admin.site.register(LocationRemapHistory, RemapAdmin) diff --git a/src/etools/libraries/locations/tests/test_views.py b/src/etools/libraries/locations/tests/test_views.py index e0e0f0c52e..1b25900d6a 100644 --- a/src/etools/libraries/locations/tests/test_views.py +++ b/src/etools/libraries/locations/tests/test_views.py @@ -16,17 +16,13 @@ def setUpTestData(cls): cls.locations.append(cls.parent) # heavy_detail_expected_keys are the keys that should be in response.data.keys() cls.heavy_detail_expected_keys = sorted( - ('id', 'name', 'name_display', 'p_code', 'gateway', 'parent', 'geo_point') + ('admin_level', 'admin_level_name', 'id', 'name', 'name_display', 'p_code', 'parent', 'geo_point') ) - def test_api_locationtypes_list(self): - response = self.forced_auth_req('get', reverse('locationtypes-list'), user=self.unicef_staff) - self.assertEqual(response.status_code, status.HTTP_200_OK) - def test_api_location_light_list(self): response = self.forced_auth_req('get', reverse('locations-light-list'), user=self.unicef_staff) self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(sorted(response.data[0].keys()), ["gateway", "id", "name", "name_display", "p_code", "parent"]) + self.assertEqual(sorted(response.data[0].keys()), ['admin_level', 'admin_level_name', "id", "name", "name_display", "p_code", "parent"]) # sort the expected locations by name, the same way the API results are sorted self.locations.sort(key=lambda location: location.name) @@ -36,14 +32,14 @@ def test_api_location_light_list(self): if location.parent: self.assertEqual(data["name"], '{} ({}: {}) -- {}'.format( location.name, - location.gateway.name, + location.admin_level_name, location.p_code, location.parent.name )) else: self.assertEqual(data["name"], '{} ({}: {})'.format( location.name, - location.gateway.name, + location.admin_level_name, location.p_code, )) @@ -117,5 +113,6 @@ def test_api_location_autocomplete(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 6) - self.assertEqual(sorted(response.data[0].keys()), ["gateway", "id", "name", "name_display", "p_code", "parent"]) + self.assertEqual(sorted(response.data[0].keys()), ['admin_level', 'admin_level_name', "id", "name", + "name_display", "p_code", "parent"]) self.assertIn("Loc", response.data[0]["name"]) diff --git a/src/etools/libraries/locations/urls.py b/src/etools/libraries/locations/urls.py index ec16a5608f..4606eddba0 100644 --- a/src/etools/libraries/locations/urls.py +++ b/src/etools/libraries/locations/urls.py @@ -2,19 +2,12 @@ from rest_framework import routers -from .views import ( - CartoDBTablesView, - LocationQuerySetView, - LocationsLightViewSet, - LocationsViewSet, - LocationTypesViewSet, -) +from .views import CartoDBTablesView, LocationQuerySetView, LocationsLightViewSet, LocationsViewSet api = routers.SimpleRouter() api.register(r'locations', LocationsViewSet, basename='locations') api.register(r'locations-light', LocationsLightViewSet, basename='locations-light') -api.register(r'locations-types', LocationTypesViewSet, basename='locationtypes') urlpatterns = [ re_path(r'^cartodbtables/$', CartoDBTablesView.as_view(), name='cartodbtables'), diff --git a/src/etools/libraries/locations/views.py b/src/etools/libraries/locations/views.py index aa0bd7c32f..5e4f111fc3 100644 --- a/src/etools/libraries/locations/views.py +++ b/src/etools/libraries/locations/views.py @@ -21,10 +21,6 @@ class LocationsViewSet(views.LocationsViewSet): pass -class LocationTypesViewSet(views.LocationTypesViewSet): - permission_classes = (permissions.IsAdminUser,) - - class LocationQuerySetView(views.LocationQuerySetView): pass From 97188f73d26d9fee888bc8828c6528448588855f Mon Sep 17 00:00:00 2001 From: Domenico Date: Fri, 11 Feb 2022 11:19:45 -0600 Subject: [PATCH 32/39] update location version --- Pipfile | 2 +- Pipfile.lock | 44 ++++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Pipfile b/Pipfile index 27419819c3..eabade275a 100644 --- a/Pipfile +++ b/Pipfile @@ -74,7 +74,7 @@ social-auth-core = {extras = ["azuread"],version = "==4.1"} tenant-schemas-celery = "==1.0.1" unicef-attachments = "==0.10.1" unicef-djangolib = "==0.5.4" -unicef-locations = "==3.2.1" +unicef-locations = "==3.2.2" unicef-notification = "==1.1" unicef-restlib = "==0.7" unicef-snapshot = "==1.1" diff --git a/Pipfile.lock b/Pipfile.lock index 9c920c24f8..e32d82de9d 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "76c4cabb1d1868637c79256e8ffb996c7028586dba6094dd86d724affebc2e6a" + "sha256": "f78768da25e26aae5e73a39985447affc1a8c461b785db7c9dbdaf37f1531796" }, "pipfile-spec": 6, "requires": { @@ -884,10 +884,10 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:cb7dae7d2c59188c85a1d6c944fad19aded6a26bd9c8ae115a4e1c20eb90b713", - "sha256:f2b6a8067a4fb959d3677d1ed764cc4e63e0f6f565b9a4fc7edc2b18bf80217b" + "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c", + "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650" ], - "version": "==3.0.27" + "version": "==3.0.28" }, "psycopg2-binary": { "hashes": [ @@ -1104,11 +1104,11 @@ }, "sentry-sdk": { "hashes": [ - "sha256:4fc7960a82c95d906a0514cf4d9aacba1743eb9863a5b7c2a01c525a7d9b21e6", - "sha256:f7e54567937ebcbe938c4df1075ec891587faeb7c74184b88cf2894e47c86116" + "sha256:3817274fba2498c8ebf6b896ee98ac916c5598706340573268c07bf2bb30d831", + "sha256:98fd155fa5d5fec1dbabed32a1a4ae2705f1edaa5dae4e7f7b62a384ba30e759" ], "index": "pypi", - "version": "==1.5.4" + "version": "==1.5.5" }, "simplejson": { "hashes": [ @@ -1301,11 +1301,11 @@ }, "unicef-locations": { "hashes": [ - "sha256:7c69221801368ec9a48e05dff1ac19fae17515c7a695790d25ee4e975f7f3731", - "sha256:e54150a1241ee061b12bdce42af59f986caa5dbf32a0a02d18f6e6e39967e31e" + "sha256:456895b1e3e71bb46e0f989ed14f8a784acb11123bc34d507a7aa36453a6bbf4", + "sha256:7d732f408861dc07034ed22b54bbd18bea029ee6280a7015b79059cf89938117" ], "index": "pypi", - "version": "==3.2.1" + "version": "==3.2.2" }, "unicef-notification": { "hashes": [ @@ -1581,10 +1581,10 @@ }, "faker": { "hashes": [ - "sha256:534c9410cd003b794900504d37f0afaf8275bfe8865583250799f696cf227cd3", - "sha256:820e55f62b428a4d55f6700358167e84a6ba3f8371e9ef39f9ca03a504dcae18" + "sha256:b996c2162448241a48155df2077458d6fcf1adcee9a6d1201bb9c06c40e8f48d", + "sha256:e1939ea638e7bacfa4dce69f872bdd7d53c1b23a92f1bd9f530590c93a4677e0" ], - "version": "==12.1.0" + "version": "==12.3.0" }, "fancycompleter": { "hashes": [ @@ -1633,11 +1633,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6", - "sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e" + "sha256:6affcdb3aec542dd98df8211e730bba6c5f2bec8288d47bacacde898f548c9ad", + "sha256:9e5e553bbba1843cb4a00823014b907616be46ee503d2b9ba001d214a8da218f" ], "markers": "python_version < '3.10'", - "version": "==4.10.1" + "version": "==4.11.0" }, "ipython": { "hashes": [ @@ -1882,10 +1882,10 @@ }, "platformdirs": { "hashes": [ - "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca", - "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda" + "sha256:30671902352e97b1eafd74ade8e4a694782bd3471685e78c32d0fdfd3aa7e7bb", + "sha256:8ec11dfba28ecc0715eb5fb0147a87b1bf325f349f3da9aab2cd6b50b96b692b" ], - "version": "==2.4.1" + "version": "==2.5.0" }, "pluggy": { "hashes": [ @@ -1896,10 +1896,10 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:cb7dae7d2c59188c85a1d6c944fad19aded6a26bd9c8ae115a4e1c20eb90b713", - "sha256:f2b6a8067a4fb959d3677d1ed764cc4e63e0f6f565b9a4fc7edc2b18bf80217b" + "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c", + "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650" ], - "version": "==3.0.27" + "version": "==3.0.28" }, "ptyprocess": { "hashes": [ From 1148bada0acae3929297e1b02a316f0fb7596efe Mon Sep 17 00:00:00 2001 From: Domenico Date: Fri, 11 Feb 2022 13:25:59 -0600 Subject: [PATCH 33/39] update location version --- Pipfile | 2 +- Pipfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Pipfile b/Pipfile index eabade275a..2c23d6369b 100644 --- a/Pipfile +++ b/Pipfile @@ -74,7 +74,7 @@ social-auth-core = {extras = ["azuread"],version = "==4.1"} tenant-schemas-celery = "==1.0.1" unicef-attachments = "==0.10.1" unicef-djangolib = "==0.5.4" -unicef-locations = "==3.2.2" +unicef-locations = "==3.2.3" unicef-notification = "==1.1" unicef-restlib = "==0.7" unicef-snapshot = "==1.1" diff --git a/Pipfile.lock b/Pipfile.lock index e32d82de9d..22fe6fb5c8 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "f78768da25e26aae5e73a39985447affc1a8c461b785db7c9dbdaf37f1531796" + "sha256": "da70c32c7d55680dae1d4dbdc512469c8e1f0a95c4163def4886e580417ae2f4" }, "pipfile-spec": 6, "requires": { @@ -1301,11 +1301,11 @@ }, "unicef-locations": { "hashes": [ - "sha256:456895b1e3e71bb46e0f989ed14f8a784acb11123bc34d507a7aa36453a6bbf4", - "sha256:7d732f408861dc07034ed22b54bbd18bea029ee6280a7015b79059cf89938117" + "sha256:172e66008117ed6703b8dd37a592fc2977712da7c59e6b498aa818329b00a8b2", + "sha256:88d0e1ecfd13bc2824999000727371d98e1b6e8b65c0d3179582ef5ba44d4c01" ], "index": "pypi", - "version": "==3.2.2" + "version": "==3.2.3" }, "unicef-notification": { "hashes": [ From 23a451acca384ae555701171895a3401c9c28b1b Mon Sep 17 00:00:00 2001 From: Domenico Date: Tue, 15 Feb 2022 09:04:29 -0600 Subject: [PATCH 34/39] 27963-integrity-error --- .../applications/management/handlers/sections.py | 2 +- src/etools/applications/management/views/sections.py | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/etools/applications/management/handlers/sections.py b/src/etools/applications/management/handlers/sections.py index 65ed30a33a..767cbcfc76 100644 --- a/src/etools/applications/management/handlers/sections.py +++ b/src/etools/applications/management/handlers/sections.py @@ -12,7 +12,7 @@ from etools.applications.tpm.models import TPMActivity, TPMVisit -class MigrationException(Exception): +class MigrationException(BaseException): """Exception thrown when migration is failing due validation""" diff --git a/src/etools/applications/management/views/sections.py b/src/etools/applications/management/views/sections.py index 0644493458..992123914d 100644 --- a/src/etools/applications/management/views/sections.py +++ b/src/etools/applications/management/views/sections.py @@ -40,11 +40,8 @@ def merge(self, request): new_section_name = request.data['new_section_name'] sections_to_merge = request.data['sections_to_merge'] logger.info('Section to Merge', sections_to_merge) - except KeyError: - return Response(_('Unable to unpack'), status=status.HTTP_400_BAD_REQUEST) - try: section = SectionHandler.merge(new_section_name, sections_to_merge) - except (IntegrityError, MigrationException) as e: + except (KeyError, IntegrityError, MigrationException) as e: return Response(str(e), status=status.HTTP_400_BAD_REQUEST) return Response({ @@ -59,9 +56,8 @@ def close(self, request): objects_dict = request.data['new_sections'] logger.info('Section Migrate', objects_dict) sections = SectionHandler.close(old_section, objects_dict) - - except (KeyError, MigrationException): - return Response(_('Unable to unpack'), status=status.HTTP_400_BAD_REQUEST) + except (KeyError, IntegrityError, MigrationException) as e: + return Response(str(e), status=status.HTTP_400_BAD_REQUEST) data = [{'id': section.id, 'name': section.name} for section in sections] return Response(data) From d7df963702e444f4e2180c9b1bf486cc0bfb72dc Mon Sep 17 00:00:00 2001 From: Domenico Date: Mon, 28 Feb 2022 08:59:39 -0600 Subject: [PATCH 35/39] fix prp sync --- src/etools/applications/partners/serializers/prp_v1.py | 2 +- .../applications/partners/tests/data/prp-intervention-list.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etools/applications/partners/serializers/prp_v1.py b/src/etools/applications/partners/serializers/prp_v1.py index 54d1e0136d..f2e668e3ca 100644 --- a/src/etools/applications/partners/serializers/prp_v1.py +++ b/src/etools/applications/partners/serializers/prp_v1.py @@ -165,7 +165,7 @@ def get_locations(self, obj): "admin_level", ) for loc in location_qs: - loc["pcode"] = loc.pop("p_code") + loc["p_code"] = loc.pop("p_code") loc["admin_level_name"] = loc.pop("admin_level_name") loc["admin_level"] = loc.pop("admin_level") return list(location_qs) diff --git a/src/etools/applications/partners/tests/data/prp-intervention-list.json b/src/etools/applications/partners/tests/data/prp-intervention-list.json index f479171130..2e8bc1707f 100644 --- a/src/etools/applications/partners/tests/data/prp-intervention-list.json +++ b/src/etools/applications/partners/tests/data/prp-intervention-list.json @@ -21,7 +21,7 @@ { "id": 1, "admin_level": 0, - "pcode": "a-p-code", + "p_code": "a-p-code", "name": "A Location", "admin_level_name": "A Gateway" } From a51802c087943f1e3c3201b069d59dea18fcdfc1 Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Tue, 1 Mar 2022 11:37:39 +0200 Subject: [PATCH 36/39] [ch28560] Admin Monitoring Activity slow loading fix --- .../field_monitoring/planning/admin.py | 18 ++++++++++++++++++ src/etools/config/settings/base.py | 8 +++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/etools/applications/field_monitoring/planning/admin.py b/src/etools/applications/field_monitoring/planning/admin.py index 5788feda34..943d8691ac 100644 --- a/src/etools/applications/field_monitoring/planning/admin.py +++ b/src/etools/applications/field_monitoring/planning/admin.py @@ -34,6 +34,24 @@ class MonitoringActivityAdmin(admin.ModelAdmin): list_select_related = ('tpm_partner', 'visit_lead', 'location', 'location_site') list_filter = ('monitor_type', 'status') + raw_id_fields = ('tpm_partner', 'visit_lead', 'location') + + def get_queryset(self, request): + return super().get_queryset(request)\ + .select_related( + 'tpm_partner', + 'visit_lead', + 'location', + 'location_site')\ + .prefetch_related( + 'team_members', + 'offices', + 'sections', + 'partners', + 'interventions', + 'cp_outputs' + ) + @admin.register(MonitoringActivityGroup) class MonitoringActivityGroupAdmin(admin.ModelAdmin): diff --git a/src/etools/config/settings/base.py b/src/etools/config/settings/base.py index 2776ba0d62..cfd07d96e2 100644 --- a/src/etools/config/settings/base.py +++ b/src/etools/config/settings/base.py @@ -246,9 +246,11 @@ def get_from_secrets_or_env(var_name, default=None): 'OPTIONS': { 'debug': DEBUG, 'loaders': [ - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - 'unicef_notification.loaders.EmailTemplateLoader', + ('django.template.loaders.cached.Loader', [ + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + 'unicef_notification.loaders.EmailTemplateLoader', + ]), ], 'context_processors': [ # Already defined Django-related contexts here From 45aa58589f9db28c3f86c5e2b292fc68ca887e3e Mon Sep 17 00:00:00 2001 From: Ema Ciupe Date: Tue, 1 Mar 2022 17:21:26 +0200 Subject: [PATCH 37/39] [ch28560] Slow Admin Monitoring Activity: add remaining to raw_id_fields --- src/etools/applications/field_monitoring/planning/admin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/etools/applications/field_monitoring/planning/admin.py b/src/etools/applications/field_monitoring/planning/admin.py index 943d8691ac..49d5103d4f 100644 --- a/src/etools/applications/field_monitoring/planning/admin.py +++ b/src/etools/applications/field_monitoring/planning/admin.py @@ -34,7 +34,9 @@ class MonitoringActivityAdmin(admin.ModelAdmin): list_select_related = ('tpm_partner', 'visit_lead', 'location', 'location_site') list_filter = ('monitor_type', 'status') - raw_id_fields = ('tpm_partner', 'visit_lead', 'location') + raw_id_fields = ('tpm_partner', 'visit_lead', 'location', + 'team_members', 'offices', 'sections', + 'partners', 'interventions', 'cp_outputs') def get_queryset(self, request): return super().get_queryset(request)\ From 70697610aa19289d00c5a62dc67f657ea0191109 Mon Sep 17 00:00:00 2001 From: Domenico Date: Tue, 1 Mar 2022 10:28:03 -0600 Subject: [PATCH 38/39] Update __init__.py --- src/etools/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etools/__init__.py b/src/etools/__init__.py index 53ac31fd9a..a83e7a3048 100644 --- a/src/etools/__init__.py +++ b/src/etools/__init__.py @@ -1,2 +1,2 @@ -VERSION = __version__ = '9.10.0' +VERSION = __version__ = '9.11.0' NAME = 'eTools' From 2af81954f92f51540435362b3be6aa4ae5fa75ed Mon Sep 17 00:00:00 2001 From: Domenico Date: Wed, 9 Mar 2022 14:10:23 -0600 Subject: [PATCH 39/39] 28554 archived location path excludes archived --- .../applications/field_monitoring/fm_settings/views.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/etools/applications/field_monitoring/fm_settings/views.py b/src/etools/applications/field_monitoring/fm_settings/views.py index 2d5f6a19d0..5f0ab1988a 100644 --- a/src/etools/applications/field_monitoring/fm_settings/views.py +++ b/src/etools/applications/field_monitoring/fm_settings/views.py @@ -141,9 +141,8 @@ class FMLocationsViewSet(FMBaseViewSet, mixins.ListModelMixin, viewsets.GenericV @action(methods=['get'], detail=True) def path(self, request, *args, **kwargs): - return Response( - data=self.get_serializer(instance=self.get_object().get_ancestors(include_self=True), many=True).data - ) + ancestors = self.get_object().get_ancestors(include_self=True).filter(is_active=True) + return Response(data=self.get_serializer(instance=ancestors, many=True).data) class LogIssuesViewSet(FMBaseViewSet, viewsets.ModelViewSet):