-
-
-
-
-{% endblock %}
From 49f7fc61a2c010de0e84488c942428a99dc0bda6 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Wed, 10 Apr 2019 14:03:07 -0400
Subject: [PATCH 39/79] added libxslt-dev
---
Dockerfile | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index a026a11d63..80f079e9ba 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -48,7 +48,9 @@ RUN apk add postgresql-client
RUN apk add openssl \
ca-certificates \
libressl2.7-libcrypto \
- libmagic
+ libmagic \
+ libxslt-dev
+
RUN apk add geos \
gdal --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/
From 64b4cd09cdc31469e8d59e2c42dd970fd0bac05c Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Wed, 10 Apr 2019 14:03:07 -0400
Subject: [PATCH 40/79] added libxslt
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 80f079e9ba..8967499576 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -49,7 +49,7 @@ RUN apk add openssl \
ca-certificates \
libressl2.7-libcrypto \
libmagic \
- libxslt-dev
+ libxslt
RUN apk add geos \
gdal --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/
From b8067de623c4171cb7ef18e63b3e88dd21028bf2 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Tue, 26 Mar 2019 11:00:39 -0400
Subject: [PATCH 41/79] clean management app
---
src/etools/applications/management/README.md | 93 -----
src/etools/applications/management/admin.py | 11 -
.../management/issues/__init__.py | 0
.../applications/management/issues/checks.py | 156 --------
.../management/issues/exceptions.py | 8 -
.../management/issues/project_checks.py | 167 --------
.../management/management/__init__.py | 0
.../management/commands/__init__.py | 0
.../management/commands/check_issues.py | 10 -
.../management/commands/recheck_issues.py | 10 -
.../migrations/0002_auto_20190326_1500.py | 20 +
src/etools/applications/management/models.py | 79 ----
src/etools/applications/management/tasks.py | 52 ---
.../management/tests/factories.py | 12 -
.../management/tests/test_commands.py | 36 --
.../management/tests/test_issue_checks.py | 253 ------------
.../tests/test_issue_project_checks.py | 359 ------------------
.../management/tests/test_models.py | 51 ---
.../management/tests/test_tasks.py | 35 --
src/etools/applications/management/urls.py | 2 -
.../management/views/tasks_endpoints.py | 7 +-
.../applications/management/views/v1.py | 5 -
22 files changed, 21 insertions(+), 1345 deletions(-)
delete mode 100644 src/etools/applications/management/README.md
delete mode 100644 src/etools/applications/management/admin.py
delete mode 100644 src/etools/applications/management/issues/__init__.py
delete mode 100644 src/etools/applications/management/issues/checks.py
delete mode 100644 src/etools/applications/management/issues/exceptions.py
delete mode 100644 src/etools/applications/management/issues/project_checks.py
delete mode 100644 src/etools/applications/management/management/__init__.py
delete mode 100644 src/etools/applications/management/management/commands/__init__.py
delete mode 100644 src/etools/applications/management/management/commands/check_issues.py
delete mode 100644 src/etools/applications/management/management/commands/recheck_issues.py
create mode 100644 src/etools/applications/management/migrations/0002_auto_20190326_1500.py
delete mode 100644 src/etools/applications/management/models.py
delete mode 100644 src/etools/applications/management/tests/factories.py
delete mode 100644 src/etools/applications/management/tests/test_commands.py
delete mode 100644 src/etools/applications/management/tests/test_issue_checks.py
delete mode 100644 src/etools/applications/management/tests/test_issue_project_checks.py
delete mode 100644 src/etools/applications/management/tests/test_models.py
delete mode 100644 src/etools/applications/management/tests/test_tasks.py
diff --git a/src/etools/applications/management/README.md b/src/etools/applications/management/README.md
deleted file mode 100644
index 91eeb44d79..0000000000
--- a/src/etools/applications/management/README.md
+++ /dev/null
@@ -1,93 +0,0 @@
-# Management App
-
-This app is currently meant to be used to flag potential issues (either bad data or policy violations).
-
-## Classes involved
-
-The main two important categories of things are *Issue Checks* (subclasses of `BaseIssueCheck`) and
-*Flagged Issues* instances of `FlaggedIssue`.
-**Both of these names might change soon.**
-
-Issue checks represent *types* of issues that can be raised. Examples of issue checks might include
-"an Agreement did not have a signed PCA attached to it" or "an Intervention failed validation".
-**Issue checks live in code.**
-
-However, each Issue check also has an associated `IssueCheckConfig` object.
-The `IssueCheckConfig` is generated automatically, and is used to turn on/off issue checks at the database level
-(instead of having to deploy code to turn on/off checks).
-`IssueCheckConfig` objects are editable in the admin.
-
-Flagged issues represent *instances* of an issue.
-For example, "*This particular Agreement* did not have a signed PCA attached to it" or
-"*this particular Intervention* failed validation".
-Flagged issues are associated with an Issue Check by ID, and also point at an associated object in the database.
-
-## High level function
-
-There are two high-level functions - provided both as management commands and celery tasks.
-
-### Check issues
-
-`./manage.py check_issues`
-
-This will run all Issue Checks against the entire database and create (or update) any relevant `FlaggedIssue` objects.
-In the future this could be updated to only test since the last check.
-
-### Recheck issues
-
-`./manage.py recheck_issues`
-
-This will re-run all checks against the current set of existing `FlaggedIssue` objects.
-If the issue has been addressed the `FlaggedIssue`'s status will be set to "resolved".
-Else it will stay active.
-
-## Adding a new check
-
-Adding a new check is a two step process:
-
-1. Create a new subclass of `BaseIssueCheck` and implement the appropriate methods
-2. Add the class to the list of `ISSUE_CHECKS` in settings/base.py
-
-### Required methods
-
-The jobs a check has are to:
-
-1. Generate a set of potentially relevant objects that should be checked.
- This is used in the code that runs all checks (`./manage.py check_issues`).
-2. Check an individual object.
- This is used both in the code that runs all checks (`./manage.py check_issues`) and the code that rechecks
- individual issues (`./manage.py recheck_issues`).
-
-#### Getting relevant objects
-
-Generally the issue check should return the smallest possible set of potential objects to check.
-The `BaseIssueCheck` class provides two ways of implementing this: either by overriding `get_queryset`
-or by overriding `get_objects_to_check`.
-
-`get_queryset` should be overridden if the relevant set of objects can be easily represented in a single queryset,
-and no additional metadata is required for the check (see below).
-
-`get_objects_to_check` should be overridden if the relevant set of objects to check is too complex to represent
-in a single queryset, or if additional metadata is needed (see below).
-
-#### Checking an individual object
-
-All issue checks must implement `run_check`, which takes an object, (optional) metadata, and should either
-do nothing (if the check is successful) or raise an `IssueFoundException` if there is something wrong.
-
-As mentioned above, this method is called during checking all issues as well as during rechecks.
-
-#### Metadata
-
-In some instances, the object itself is not enough information to run the check.
-For example, when validating an `Intervention`'s lower result data matches the correct `CountryProgramme`
-you need to know which `CountryProgramme` you are looking at.
-In this scenario you should to include a dictionary of metadata with the check.
-
-The metadata needs to be provided in two places:
-
-1. In the `get_objects_to_check` function - so it can be passed during normal checks.
-2. By overriding `get_object_metadata` in the issue check - so the metadata can be reconstructed from
- the `FlaggedIssue` object during rechecks.
-
-See `PdOutputsWrongCheck` for an example of check metadata in use.
diff --git a/src/etools/applications/management/admin.py b/src/etools/applications/management/admin.py
deleted file mode 100644
index 78afc88489..0000000000
--- a/src/etools/applications/management/admin.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from django.contrib import admin
-
-from . import models as app_models
-
-
-@admin.register(app_models.FlaggedIssue)
-class FlaggedIssueAdmin(admin.ModelAdmin):
- list_display = ['content_object', 'issue_category', 'issue_id', 'issue_status', 'date_created',
- 'date_updated', 'message']
- list_filter = ['issue_category', 'issue_id', 'issue_status', 'date_created', 'date_updated']
- search_fields = ['message']
diff --git a/src/etools/applications/management/issues/__init__.py b/src/etools/applications/management/issues/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/etools/applications/management/issues/checks.py b/src/etools/applications/management/issues/checks.py
deleted file mode 100644
index db75861802..0000000000
--- a/src/etools/applications/management/issues/checks.py
+++ /dev/null
@@ -1,156 +0,0 @@
-
-import logging
-from abc import ABCMeta, abstractmethod
-from collections import namedtuple
-
-from django.conf import settings
-from django.core.exceptions import ImproperlyConfigured
-from django.db.models import Model
-
-from django.utils.module_loading import import_string
-
-from etools.applications.environment.models import IssueCheckConfig
-from etools.applications.management.issues.exceptions import IssueCheckNotFoundException, IssueFoundException
-from etools.applications.management.models import FlaggedIssue, ISSUE_STATUS_RESOLVED
-from etools.libraries.tenant_support.utils import run_on_all_tenants
-
-ModelCheckData = namedtuple('ModelCheckData', 'object metadata')
-
-
-class BaseIssueCheck(metaclass=ABCMeta):
- """
- Base class for all Issue Checks
- """
- model = None # the model class that this check runs against.
- check_id = None # a unique id for the issue check type.
-
- def __init__(self):
- if self.model is None or not issubclass(self.model, Model):
- raise ImproperlyConfigured('Issue checks must define a model class that subclasses models.Model!')
- if not self.check_id:
- raise ImproperlyConfigured('Issue checks must define a unique ID!')
-
- def check_all(self):
- """
- Check all objects for issues.
- """
- def _inner():
- for model_instance, metadata in self.get_objects_to_check():
- try:
- self.run_check(model_instance, metadata)
- except IssueFoundException as e:
- issue = FlaggedIssue.get_or_new(content_object=model_instance, issue_id=self.check_id)
- issue.message = str(e)
- issue.save()
- # todo: is it always valid to run all checks against all tenants?
- run_on_all_tenants(_inner)
-
- def get_queryset(self):
- """
- The default queryset of data to be checked.
- """
- return self.model.objects.all()
-
- def get_objects_to_check(self):
- """
- An iterable returning the ModelCheckData objects over which this check should be performed.
- Should return an iterable/queryset of ModelCheckData with object being an instance of self.model
- and metadata being an optional dictionary of additional data needed by the check.
-
- The default just returns the results of self.get_queryset with empty metadata
- """
- for object in self.get_queryset():
- yield ModelCheckData(object, {})
-
- def get_object_metadata(self, model_instance):
- """
- Return any necessary metadata associated with an object. Necessary during rechecks.
- """
- return {}
-
- @abstractmethod
- def run_check(self, model_instance, metadata):
- """
- This method should raise an IssueFoundException if the check fails.
- """
-
-
-def get_available_issue_checks():
- """
- Get all issue checks from the configured settings.
- """
- check_ids = set()
- for check_path in settings.ISSUE_CHECKS:
- check = get_issue_check(check_path)
- if check.check_id in check_ids:
- raise ImproperlyConfigured(
- 'Duplicate Issue Check ID {} is not allowed! See settings.ISSUE_CHECKS'.format(check.check_id)
- )
- check_ids.add(check.check_id)
- yield get_issue_check(check_path)
-
-
-def get_active_issue_checks():
- """
- Get all *active* issue checks from the configured settings / database.
- """
- bootstrap_checks(default_is_active=False)
- active_checks = set(IssueCheckConfig.objects.filter(is_active=True).values_list('check_id', flat=True))
- for check in get_available_issue_checks():
- if check.check_id in active_checks:
- yield check
-
-
-def get_issue_check_by_id(check_id):
- # todo: might make sense to cache this if it's going to be called frequently
- for check in get_available_issue_checks():
- if check.check_id == check_id:
- return check
- raise IssueCheckNotFoundException('No issue check with ID {} found.'.format(check_id))
-
-
-# todo: should probably cache this with something like lru_cache
-def get_issue_check(import_path):
- """
- Import the issue check class described by import_path, where
- import_path is the full Python path to the class.
- """
- IssueCheck = import_string(import_path)
- if not issubclass(IssueCheck, BaseIssueCheck):
- raise ImproperlyConfigured('Issue Check "%s" is not a subclass of "%s"' %
- (IssueCheck, BaseIssueCheck))
- return IssueCheck()
-
-
-def run_all_checks():
- """
- Run all configured issue checks. Note that this function might take a long time to complete on a large
- database.
- """
- for issue_check in get_active_issue_checks():
- issue_check.check_all()
-
-
-def recheck_all_open_issues():
- """
- Recheck all unresolved FlaggedIssue objects for resolution.
- """
- def _check():
- for issue in FlaggedIssue.objects.exclude(issue_status=ISSUE_STATUS_RESOLVED):
- try:
- issue.recheck()
- except IssueCheckNotFoundException as e:
- # todo: should this fail hard?
- logging.error(str(e))
-
- # todo: is it always valid to run all checks against all tenants?
- run_on_all_tenants(_check)
-
-
-def bootstrap_checks(default_is_active=False):
- """
- Bootstraps the IssueCheckConfig objects for all IssueChecks in the database.
- """
- for issue_check in get_available_issue_checks():
- if not IssueCheckConfig.objects.filter(check_id=issue_check.check_id).exists():
- IssueCheckConfig.objects.create(check_id=issue_check.check_id, is_active=default_is_active)
diff --git a/src/etools/applications/management/issues/exceptions.py b/src/etools/applications/management/issues/exceptions.py
deleted file mode 100644
index 9e92d53b9d..0000000000
--- a/src/etools/applications/management/issues/exceptions.py
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-class IssueFoundException(Exception):
- pass
-
-
-class IssueCheckNotFoundException(Exception):
- pass
diff --git a/src/etools/applications/management/issues/project_checks.py b/src/etools/applications/management/issues/project_checks.py
deleted file mode 100644
index 9259c40f32..0000000000
--- a/src/etools/applications/management/issues/project_checks.py
+++ /dev/null
@@ -1,167 +0,0 @@
-import logging
-
-from django.contrib.auth import get_user_model
-from django.db.models import Q
-
-from etools.applications.management.issues.checks import BaseIssueCheck, ModelCheckData
-from etools.applications.management.issues.exceptions import IssueFoundException
-from etools.applications.partners.models import Agreement, AgreementAmendment, Intervention, InterventionAmendment
-from etools.applications.partners.validation.interventions import InterventionValid
-from etools.applications.reports.models import CountryProgramme
-
-# todo: these can probably move closer to the models they are associated with, but just
-# starting with them here as a proof of concept
-
-
-class ActivePCANoSignedDocCheck(BaseIssueCheck):
- model = Agreement
- check_id = 'active_pca_no_signed_doc'
-
- def get_queryset(self):
- return Agreement.objects.filter(agreement_type=Agreement.PCA).exclude(status='draft')
-
- def run_check(self, model_instance, metadata):
- if not model_instance.attached_agreement:
- raise IssueFoundException(
- '{} Agreement [{}] does not have a signed PCA attached'.format(model_instance.agreement_type,
- model_instance.id)
- )
-
-
-class PdOutputsWrongCheck(BaseIssueCheck):
- model = Intervention
- check_id = 'pd_outputs_wrong'
-
- def get_objects_to_check(self):
- cps = CountryProgramme.objects.filter(invalid=False, wbs__contains='/A0/')
- for cp in cps:
- interventions = Intervention.objects.filter(
- start__gte=cp.from_date, start__lte=cp.to_date
- ).prefetch_related('result_links')
- for intervention in interventions:
- yield ModelCheckData(intervention, {'cp': cp})
-
- def get_object_metadata(self, model_instance):
- # todo: confirm this logic is always valid
- cp = CountryProgramme.objects.filter(
- invalid=False,
- wbs__contains='/A0/',
- from_date__lte=model_instance.start,
- to_date__gte=model_instance.end,
- ).first()
- return {'cp': cp}
-
- def run_check(self, model_instance, metadata):
- wrong_cp = []
- cp = metadata['cp']
- if cp is None:
- logging.error(
- (
- "Tried to check PD Outputs without a linked CountryProgramme for Intervention {}. "
- "This will be ignored and any associated issues may be resolved."
- ).format(model_instance.pk)
- )
- return
- for rl in model_instance.result_links.all():
- if rl.cp_output.country_programme != cp:
- wrong_cp.append(rl.cp_output.wbs)
- if len(wrong_cp) > 0:
- raise IssueFoundException(
- "PD [P{}] STATUS [{}] CP [{}] has wrongly mapped outputs {}".format(
- model_instance.id, model_instance.status, cp.wbs, wrong_cp)
- )
-
-
-class InterventionsAssociatedSSFACheck(BaseIssueCheck):
- model = Intervention
- check_id = 'interventions_associated_ssfa'
-
- def get_queryset(self):
- return Intervention.objects.filter(
- Q(agreement__agreement_type=Agreement.SSFA, document_type=Intervention.PD) |
- Q(agreement__agreement_type=Agreement.PCA, document_type=Intervention.SSFA)
- ).prefetch_related('agreement')
-
- def run_check(self, model_instance, metadata):
- # in this case the queryset controls the issue, so all relevant objects should fail,
- # but we still need the test to be inside `run_check` so that objects can be rechecked
- # in the future
- fails_test = (
- (
- model_instance.agreement.agreement_type == Agreement.SSFA and
- model_instance.document_type == Intervention.PD
- ) or (
- model_instance.agreement.agreement_type == Agreement.PCA and
- model_instance.document_type == Intervention.SSFA
- )
- )
- if fails_test:
- raise IssueFoundException(
- 'intervention {} type {} status {} has agreement type {}'.format(
- model_instance.id, model_instance.document_type,
- model_instance.agreement.agreement_type, model_instance.status
- )
- )
-
-
-class InterventionsAreValidCheck(BaseIssueCheck):
- model = Intervention
- check_id = 'interventions_are_valid'
-
- @staticmethod
- def _get_master_user():
- return get_user_model().objects.get(username='etools_task_admin')
-
- def get_objects_to_check(self):
- master_user = self._get_master_user()
- for intervention in Intervention.objects.filter(status__in=['draft', 'signed', 'active', 'ended']):
- yield ModelCheckData(intervention, {'master_user': master_user})
-
- def get_object_metadata(self, model_instance):
- return {'master_user': self._get_master_user()}
-
- def run_check(self, model_instance, metadata):
- master_user = metadata['master_user']
- validator = InterventionValid(model_instance, master_user)
- if not validator.is_valid:
- raise IssueFoundException(
- 'intervention {} of type {} is invalid: (Status:{}), Errors: {}'.format(
- model_instance.id, model_instance.document_type, model_instance.status,
- ', '.join(validator.errors)
- )
- )
-
-
-class PDAmendmentsMissingFilesCheck(BaseIssueCheck):
- model = InterventionAmendment
- check_id = 'interventions_amendments_no_file'
-
- def get_queryset(self):
- return InterventionAmendment.objects.filter(signed_amendment='').prefetch_related('intervention')
-
- def run_check(self, model_instance, metadata):
- if not model_instance.signed_amendment:
- raise IssueFoundException(
- 'intervention {} type {} status {} has missing amendment file'.format(
- model_instance.intervention.id,
- model_instance.intervention.document_type,
- model_instance.intervention.status)
- )
-
-
-class PCAAmendmentsMissingFilesCheck(BaseIssueCheck):
- model = AgreementAmendment
- check_id = 'agreement_amendments_no_file'
-
- def get_queryset(self):
- return AgreementAmendment.objects.filter(signed_amendment='')
-
- def run_check(self, model_instance, metadata):
- if not model_instance.signed_amendment:
- raise IssueFoundException(
- 'agreement {} type {} status {} has missing amendment file'.format(
- model_instance.agreement.id,
- model_instance.agreement.agreement_type,
- model_instance.agreement.status
- )
- )
diff --git a/src/etools/applications/management/management/__init__.py b/src/etools/applications/management/management/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/etools/applications/management/management/commands/__init__.py b/src/etools/applications/management/management/commands/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/etools/applications/management/management/commands/check_issues.py b/src/etools/applications/management/management/commands/check_issues.py
deleted file mode 100644
index 5b878b0c49..0000000000
--- a/src/etools/applications/management/management/commands/check_issues.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from django.core.management import BaseCommand
-
-from etools.applications.management.issues.checks import run_all_checks
-
-
-class Command(BaseCommand):
- help = 'Run all configured issue checks'
-
- def handle(self, *args, **options):
- run_all_checks()
diff --git a/src/etools/applications/management/management/commands/recheck_issues.py b/src/etools/applications/management/management/commands/recheck_issues.py
deleted file mode 100644
index 1db2234fbc..0000000000
--- a/src/etools/applications/management/management/commands/recheck_issues.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from django.core.management import BaseCommand
-
-from etools.applications.management.issues.checks import recheck_all_open_issues
-
-
-class Command(BaseCommand):
- help = 'Recheck all open FlaggedIssues'
-
- def handle(self, *args, **options):
- recheck_all_open_issues()
diff --git a/src/etools/applications/management/migrations/0002_auto_20190326_1500.py b/src/etools/applications/management/migrations/0002_auto_20190326_1500.py
new file mode 100644
index 0000000000..4dfee07928
--- /dev/null
+++ b/src/etools/applications/management/migrations/0002_auto_20190326_1500.py
@@ -0,0 +1,20 @@
+# Generated by Django 2.1.7 on 2019-03-26 15:00
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('management', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='flaggedissue',
+ name='content_type',
+ ),
+ migrations.DeleteModel(
+ name='FlaggedIssue',
+ ),
+ ]
diff --git a/src/etools/applications/management/models.py b/src/etools/applications/management/models.py
deleted file mode 100644
index a1973dd4f9..0000000000
--- a/src/etools/applications/management/models.py
+++ /dev/null
@@ -1,79 +0,0 @@
-
-from django.contrib.contenttypes.fields import GenericForeignKey
-from django.contrib.contenttypes.models import ContentType
-from django.db import models
-from django.utils.translation import ugettext as _
-
-from etools.applications.management.issues.exceptions import IssueFoundException
-
-ISSUE_CATEGORY_DATA = 'data'
-ISSUE_CATEGORY_COMPLIANCE = 'compliance'
-ISSUE_CATEGORY_CHOICES = (
- (ISSUE_CATEGORY_DATA, 'Data Issue'),
- (ISSUE_CATEGORY_COMPLIANCE, 'Compliance Issue'),
-)
-
-ISSUE_STATUS_NEW = 'new'
-ISSUE_STATUS_PENDING = 'pending'
-ISSUE_STATUS_REACTIVATED = 'reactivated'
-ISSUE_STATUS_RESOLVED = 'resolved'
-ISSUE_STATUS_CHOICES = (
- (ISSUE_STATUS_NEW, 'New (untriaged)'),
- (ISSUE_STATUS_PENDING, 'Pending (triaged, not resolved)'),
- (ISSUE_STATUS_REACTIVATED, 'Reactivated (was resolved but not fixed)'),
- (ISSUE_STATUS_RESOLVED, 'Resolved'),
-)
-
-
-class FlaggedIssue(models.Model):
- # generic foreign key to any object in the DB
- # https://docs.djangoproject.com/en/1.11/ref/contrib/contenttypes/#generic-relations
- content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, verbose_name=_('Content Type'))
- object_id = models.PositiveIntegerField(db_index=True, verbose_name=_('Object ID'))
- content_object = GenericForeignKey('content_type', 'object_id')
-
- date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Creation Date'))
- date_updated = models.DateTimeField(auto_now=True, verbose_name=_('Updated Date'))
- issue_category = models.CharField(max_length=32, choices=ISSUE_CATEGORY_CHOICES, default=ISSUE_CATEGORY_DATA,
- db_index=True, verbose_name=_('Issue Category'))
- issue_status = models.CharField(max_length=32, choices=ISSUE_STATUS_CHOICES, default=ISSUE_STATUS_NEW,
- db_index=True, verbose_name=_('Issue Status'))
- issue_id = models.CharField(
- max_length=100,
- help_text='A readable ID associated with the specific issue, e.g. "pca-no-attachment"',
- db_index=True,
- verbose_name=_('Issue ID')
- )
- message = models.TextField(verbose_name=_('Message'))
-
- def recheck(self):
- from etools.applications.management.issues.checks import get_issue_check_by_id # noqa
- check = get_issue_check_by_id(self.issue_id)
- try:
- check.run_check(self.content_object, metadata=check.get_object_metadata(self.content_object))
- except IssueFoundException as e:
- # don't change status unless it was marked resolved
- if self.issue_status == ISSUE_STATUS_RESOLVED:
- self.issue_status = ISSUE_STATUS_REACTIVATED
- self.message = str(e)
- self.save()
- else:
- self.issue_status = ISSUE_STATUS_RESOLVED
- self.save()
-
- @classmethod
- def get_or_new(cls, content_object, issue_id):
- """
- Like get_or_create except doesn't actually create the object in the database, and only
- allows for a limited set of fields.
- """
- try:
- # we can't query on content_object directly without defining a GenericRelation on every
- # model, so just do it manually from the content type and id
- ct = ContentType.objects.get_for_model(content_object)
- return cls.objects.get(content_type=ct, object_id=content_object.pk, issue_id=issue_id)
- except FlaggedIssue.DoesNotExist:
- return cls(content_object=content_object, issue_id=issue_id)
-
- def __str__(self):
- return self.message
diff --git a/src/etools/applications/management/tasks.py b/src/etools/applications/management/tasks.py
index 42b2724ba5..3cdd6ef02b 100644
--- a/src/etools/applications/management/tasks.py
+++ b/src/etools/applications/management/tasks.py
@@ -9,8 +9,6 @@
from dateutil.relativedelta import relativedelta
from etools.applications.core.util_scripts import set_country
-from etools.applications.audit.models import Audit, Engagement, MicroAssessment, SpecialAudit, SpotCheck
-from etools.applications.management.issues.checks import recheck_all_open_issues, run_all_checks
from etools.applications.partners.models import Intervention, PartnerOrganization
from etools.applications.users.models import Country
from etools.config.celery import app
@@ -18,22 +16,6 @@
logger = logging.getLogger(__name__)
-@app.task
-def run_all_checks_task():
- """
- Run all configured IssueChecks against the entire database.
- """
- run_all_checks()
-
-
-@app.task
-def recheck_all_open_issues_task():
- """
- Recheck all unresolved FlaggedIssue objects for resolution.
- """
- recheck_all_open_issues()
-
-
@app.task
def send_test_email(*args, **kwargs):
"""Task which send a test email"""
@@ -163,37 +145,3 @@ def pmp_indicator_report(writer, **kwargs):
'Partner Link': '{}/pmp/partners/{}/details'.format(base_url, partner.pk),
'Intervention Link': '{}/pmp/interventions/{}/details'.format(base_url, intervention.pk),
})
-
-
-@app.task
-def fam_report(writer, **kwargs):
- countries = kwargs.get('countries', None)
- start_date = kwargs.get('start_date', None)
- if start_date:
- start_date = datetime.strptime(start_date.pop(), '%Y-%m-%d')
- else:
- start_date = date.today() + relativedelta(months=-1)
-
- engagements = (SpotCheck, Audit, SpecialAudit, MicroAssessment)
- fieldnames = ['Country'] + ['{}-{}'.format(model._meta.verbose_name_raw, status_display)
- for model in engagements for _, status_display in Engagement.STATUSES]
- dict_writer = writer(fieldnames=fieldnames)
- dict_writer.writeheader()
-
- qs = Country.objects.exclude(schema_name__in=['public', 'uat', 'frg'])
- if countries:
- qs = qs.filter(schema_name__in=countries.pop().split(','))
-
- for country in qs:
- set_country(country.name)
- row_dict = {'Country': country.name}
- for model in engagements:
- for status, status_display in Engagement.STATUSES:
- filter_dict = {
- 'status': status,
- 'start_date__month': start_date.month,
- 'start_date__year': start_date.year,
- }
- row_dict['{}-{}'.format(
- model._meta.verbose_name_raw, status_display)] = model.objects.filter(**filter_dict).count()
- dict_writer.writerow(row_dict)
diff --git a/src/etools/applications/management/tests/factories.py b/src/etools/applications/management/tests/factories.py
deleted file mode 100644
index b480b64004..0000000000
--- a/src/etools/applications/management/tests/factories.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import factory
-from factory import fuzzy
-
-from etools.applications.management import models
-
-
-class FlaggedIssueFactory(factory.django.DjangoModelFactory):
- class Meta:
- model = models.FlaggedIssue
-
- issue_id = fuzzy.FuzzyText(length=50)
- message = fuzzy.FuzzyText(length=100)
diff --git a/src/etools/applications/management/tests/test_commands.py b/src/etools/applications/management/tests/test_commands.py
deleted file mode 100644
index 9f4842916e..0000000000
--- a/src/etools/applications/management/tests/test_commands.py
+++ /dev/null
@@ -1,36 +0,0 @@
-
-from django.core.management import call_command
-
-from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.management.issues import checks
-from etools.applications.management.models import FlaggedIssue, ISSUE_STATUS_NEW, ISSUE_STATUS_RESOLVED
-from etools.applications.management.tests.factories import FlaggedIssueFactory
-from etools.applications.partners.tests.factories import InterventionAmendmentFactory
-from etools.applications.users.tests.factories import UserFactory
-
-
-class TestCheckIssuesCommand(BaseTenantTestCase):
- def test_run_all_checks(self):
- UserFactory(username="etools_task_admin")
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="interventions_amendments_no_file"
- )
- InterventionAmendmentFactory(signed_amendment=None)
- checks.bootstrap_checks(default_is_active=True)
- self.assertFalse(qs_issue.exists())
- call_command("check_issues")
- self.assertTrue(qs_issue.exists())
-
-
-class TestRecheckIssuesCommand(BaseTenantTestCase):
- def test_recheck_all_open_issues_task(self):
- UserFactory(username="etools_task_admin")
- amendment = InterventionAmendmentFactory()
- issue = FlaggedIssueFactory(
- content_object=amendment,
- issue_id='interventions_amendments_no_file',
- issue_status=ISSUE_STATUS_NEW,
- )
- call_command("recheck_issues")
- issue_updated = FlaggedIssue.objects.get(pk=issue.pk)
- self.assertEqual(issue_updated.issue_status, ISSUE_STATUS_RESOLVED)
diff --git a/src/etools/applications/management/tests/test_issue_checks.py b/src/etools/applications/management/tests/test_issue_checks.py
deleted file mode 100644
index 0293954633..0000000000
--- a/src/etools/applications/management/tests/test_issue_checks.py
+++ /dev/null
@@ -1,253 +0,0 @@
-from django.core.exceptions import ImproperlyConfigured
-from django.test import override_settings
-
-from etools.applications.environment.models import IssueCheckConfig
-from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.management.issues import checks
-from etools.applications.management.issues.exceptions import IssueCheckNotFoundException, IssueFoundException
-from etools.applications.management.models import (FlaggedIssue, ISSUE_STATUS_NEW,
- ISSUE_STATUS_REACTIVATED, ISSUE_STATUS_RESOLVED,)
-from etools.applications.management.tests.factories import FlaggedIssueFactory
-from etools.applications.partners.models import PartnerOrganization
-from etools.applications.partners.tests.factories import PartnerFactory
-
-
-class PartnersMustHaveShortNameTestCheck(checks.BaseIssueCheck):
- model = PartnerOrganization
- check_id = 'partners_must_have_short_name'
-
- def get_queryset(self):
- return PartnerOrganization.objects.all()
-
- def run_check(self, model_instance, metadata):
- if not model_instance.short_name:
- raise IssueFoundException(
- 'Partner {} must specify a short name!'.format(model_instance.name)
- )
-
-
-class PartnersNameMustBeFooTestCheck(checks.BaseIssueCheck):
- model = PartnerOrganization
- check_id = 'partners_must_have_short_name'
-
- def get_object_metadata(self, model_instance):
- return {'expected_name': 'foo'}
-
- def get_objects_to_check(self):
- for org in PartnerOrganization.objects.all():
- yield checks.ModelCheckData(org, self.get_object_metadata(org))
-
- def run_check(self, model_instance, metadata):
- if model_instance.name != metadata['expected_name']:
- raise IssueFoundException(
- 'Partner name "{}" does not match expected name "{}"!'.format(
- model_instance.name, metadata['expected_name'])
- )
-
-
-class TestMissingRunCheck(checks.BaseIssueCheck):
- model = PartnerOrganization
- check_id = "must_override_run_check"
-
-
-class TestMissingModelCheck(checks.BaseIssueCheck):
- check_id = "must_override_run_check"
-
- def run_check(self, model_instance, metadata):
- return True
-
-
-class TestMissingCheckIDCheck(checks.BaseIssueCheck):
- model = PartnerOrganization
-
- def run_check(self, model_instance, metadata):
- return True
-
-
-class TestInvalidSubClass(object):
- """Invalid subclassing"""
-
-
-class IssueCheckTest(BaseTenantTestCase):
-
- def tearDown(self):
- FlaggedIssue.objects.all().delete()
- IssueCheckConfig.objects.all().delete()
- super().tearDown()
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.tests.test_issue_checks.TestMissingRunCheck'])
- def test_missing_run_check(self):
- with self.assertRaisesRegexp(TypeError, "with abstract methods run_check"):
- checks.run_all_checks()
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.tests.test_issue_checks.TestMissingModelCheck'])
- def test_missing_model(self):
- with self.assertRaisesRegexp(ImproperlyConfigured, "Issue checks must define a model class"):
- checks.run_all_checks()
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.tests.test_issue_checks.TestMissingCheckIDCheck'])
- def test_missing_check_id(self):
- with self.assertRaisesRegexp(ImproperlyConfigured, "Issue checks must define a unique ID!"):
- checks.run_all_checks()
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_get_available_issue_checks(self):
- check_list = list(checks.get_available_issue_checks())
- self.assertEqual(1, len(check_list))
- self.assertTrue(type(check_list[0]) == PartnersMustHaveShortNameTestCheck)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_bootstrap_checks(self):
- checks.bootstrap_checks()
- self.assertEqual(1, IssueCheckConfig.objects.count())
- self.assertEqual(False,
- IssueCheckConfig.objects.get(check_id='partners_must_have_short_name').is_active)
- # make sure rerunning doesn't recreate
- checks.bootstrap_checks(default_is_active=True)
- self.assertEqual(1, IssueCheckConfig.objects.count())
- # or modify existing checks
- self.assertEqual(False,
- IssueCheckConfig.objects.get(check_id='partners_must_have_short_name').is_active)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_get_active_issue_checks(self):
- checks.bootstrap_checks(default_is_active=False)
- self.assertEqual([], list(checks.get_active_issue_checks()))
- check_config = IssueCheckConfig.objects.get(check_id='partners_must_have_short_name')
- check_config.is_active = True
- check_config.save()
- check_list = list(checks.get_active_issue_checks())
- self.assertEqual(1, len(check_list))
- self.assertTrue(type(check_list[0]) == PartnersMustHaveShortNameTestCheck)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck',
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_get_available_issue_checks_disallows_duplicates(self):
- with self.assertRaises(ImproperlyConfigured):
- list(checks.get_available_issue_checks())
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_get_issue_check_by_id(self):
- check = checks.get_issue_check_by_id(PartnersMustHaveShortNameTestCheck.check_id)
- self.assertTrue(type(check) == PartnersMustHaveShortNameTestCheck)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_get_issue_check_by_id_not_found(self):
- with self.assertRaises(IssueCheckNotFoundException):
- checks.get_issue_check_by_id('not_found')
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.tests.test_issue_checks.TestInvalidSubClass'])
- def test_get_issue_check_invalid(self):
- with self.assertRaisesRegexp(ImproperlyConfigured, "is not a subclass"):
- checks.get_issue_check('etools.applications.management.tests.test_issue_checks.TestInvalidSubClass')
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_run_all_checks(self):
- PartnerFactory(short_name='A name') # make a good one as well just to ensure it's not flagging everything
- partner_bad = PartnerFactory()
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertEqual(1, FlaggedIssue.objects.count())
- issue = FlaggedIssue.objects.first()
- self.assertEqual(PartnersMustHaveShortNameTestCheck.check_id, issue.issue_id)
- self.assertEqual(partner_bad, issue.content_object)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_recheck(self):
- partner_bad = PartnerFactory()
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertEqual(1, FlaggedIssue.objects.count())
- issue = FlaggedIssue.objects.first()
- self.assertEqual(PartnersMustHaveShortNameTestCheck.check_id, issue.issue_id)
- self.assertEqual(partner_bad, issue.content_object)
- self.assertEqual(ISSUE_STATUS_NEW, issue.issue_status)
- update_date = issue.date_updated
- # initial recheck should not do anything except modify timestamps
- issue = FlaggedIssue.objects.get(pk=issue.pk)
- issue.recheck()
- self.assertEqual(ISSUE_STATUS_NEW, issue.issue_status)
- self.assertNotEqual(update_date, issue.date_updated)
- update_date = issue.date_updated
-
- # recheck after fixing the issue should update the status to resolved
- partner_bad.short_name = 'Name added'
- partner_bad.save()
- issue = FlaggedIssue.objects.get(pk=issue.pk)
- issue.recheck()
- self.assertEqual(ISSUE_STATUS_RESOLVED, issue.issue_status)
- self.assertNotEqual(update_date, issue.date_updated)
- update_date = issue.date_updated
-
- # recheck after re-creating the issue should update the status to reactivated
- partner_bad.short_name = ''
- partner_bad.save()
- issue = FlaggedIssue.objects.get(pk=issue.pk)
- issue.recheck()
- self.assertEqual(ISSUE_STATUS_REACTIVATED, issue.issue_status)
- self.assertNotEqual(update_date, issue.date_updated)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersNameMustBeFooTestCheck'])
- def test_recheck_with_metadata(self):
- partner_bad = PartnerFactory(name='bar')
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertEqual(1, FlaggedIssue.objects.count())
- issue = FlaggedIssue.objects.first()
- self.assertEqual(PartnersNameMustBeFooTestCheck.check_id, issue.issue_id)
- self.assertEqual(partner_bad, issue.content_object)
- self.assertEqual(ISSUE_STATUS_NEW, issue.issue_status)
-
- partner_bad.name = 'foo'
- partner_bad.save()
- issue = FlaggedIssue.objects.get(pk=issue.pk)
- issue.recheck()
- self.assertEqual(ISSUE_STATUS_RESOLVED, issue.issue_status)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.tests.test_issue_checks.PartnersMustHaveShortNameTestCheck'])
- def test_recheck_all_open_issues(self):
- """Check that recheck_all_open_issues call changes those issues
- that are not resolved
- And handles invalid issues
- """
- partner = PartnerFactory(short_name='A name')
- issue_resolved = FlaggedIssueFactory(
- content_object=partner,
- issue_id='partners_must_have_short_name',
- issue_status=ISSUE_STATUS_RESOLVED,
- )
- issue_new = FlaggedIssueFactory(
- content_object=partner,
- issue_id='partners_must_have_short_name',
- issue_status=ISSUE_STATUS_NEW,
- )
- issue_bad = FlaggedIssueFactory(
- content_object=partner,
- issue_status=ISSUE_STATUS_NEW,
- )
- checks.recheck_all_open_issues()
- issue_resolved_updated = FlaggedIssue.objects.get(pk=issue_resolved.pk)
- self.assertEqual(
- issue_resolved_updated.date_updated,
- issue_resolved.date_updated
- )
- issue_new_updated = FlaggedIssue.objects.get(pk=issue_new.pk)
- self.assertNotEqual(
- issue_new_updated.date_updated,
- issue_new.date_updated
- )
- issue_bad_updated = FlaggedIssue.objects.get(pk=issue_bad.pk)
- self.assertEqual(
- issue_bad_updated.date_updated,
- issue_bad.date_updated
- )
diff --git a/src/etools/applications/management/tests/test_issue_project_checks.py b/src/etools/applications/management/tests/test_issue_project_checks.py
deleted file mode 100644
index 2c29fe5452..0000000000
--- a/src/etools/applications/management/tests/test_issue_project_checks.py
+++ /dev/null
@@ -1,359 +0,0 @@
-
-import datetime
-from unittest import skip
-
-from django.test import override_settings
-
-from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.management.issues import checks
-from etools.applications.management.models import FlaggedIssue
-from etools.applications.partners.models import Agreement, Intervention, InterventionResultLink
-from etools.applications.partners.tests.factories import (AgreementAmendmentFactory, AgreementFactory,
- CountryProgrammeFactory, InterventionAmendmentFactory,
- InterventionFactory,)
-from etools.applications.partners.validation.interventions import InterventionValid
-from etools.applications.reports.tests.factories import ResultFactory
-from etools.applications.users.tests.factories import UserFactory
-
-
-class TestActivePCANoSignedDocCheck(BaseTenantTestCase):
- def setUp(self):
- super().setUp()
- UserFactory(username="etools_task_admin")
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.issues.project_checks.ActivePCANoSignedDocCheck'])
- def test_issue_found(self):
- """Check that if no attached agreement, then an issue is raised"""
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="active_pca_no_signed_doc"
- )
- agreement = AgreementFactory(attached_agreement=None)
- self.assertFalse(agreement.attached_agreement)
- self.assertEqual(agreement.agreement_type, Agreement.PCA)
-
- self.assertFalse(qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertTrue(qs_issue.exists())
- issue = qs_issue.first()
- self.assertIn("does not have a signed PCA attached", issue.message)
-
- @skip("skipping for now issues are not used and tests sometimes fail on second run")
- def test_no_issue(self):
- """Check that is attached agreement, then no issue"""
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="active_pca_no_signed_doc"
- )
- agreement = AgreementFactory()
- self.assertTrue(agreement.attachment.exists())
- self.assertEqual(agreement.agreement_type, Agreement.PCA)
-
- self.assertFalse(qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(qs_issue.exists())
-
-
-class TestPdOutputsWrongCheck(BaseTenantTestCase):
- def setUp(self):
- super().setUp()
- UserFactory(username="etools_task_admin")
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.issues.project_checks.PdOutputsWrongCheck'])
- def test_issue_found(self):
- """Check that is country programme for intervention does not
- match result country programme then issue is created"""
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="pd_outputs_wrong"
- )
- start_date = datetime.date(2001, 1, 1)
- end_date = datetime.date(2001, 12, 31)
- country = CountryProgrammeFactory(
- from_date=start_date,
- to_date=end_date,
- )
- intervention = InterventionFactory(
- country_programme=country,
- start=start_date,
- )
- result = ResultFactory(country_programme=CountryProgrammeFactory())
- InterventionResultLink.objects.create(
- intervention=intervention,
- cp_output=result,
- )
- self.assertNotEqual(
- intervention.country_programme,
- result.country_programme
- )
-
- self.assertFalse(qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertTrue(qs_issue.exists())
- issue = qs_issue.first()
- self.assertIn("has wrongly mapped outputs", issue.message)
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.issues.project_checks.PdOutputsWrongCheck'])
- def test_no_interventions(self):
- """If intervention does not fit in with Country Programmes
- then no issues raised
- """
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="pd_outputs_wrong"
- )
- start_date = datetime.date(2001, 1, 1)
- end_date = datetime.date(2001, 12, 31)
- country = CountryProgrammeFactory(
- from_date=start_date,
- to_date=end_date,
- )
- intervention = InterventionFactory(
- country_programme=country,
- start=start_date - datetime.timedelta(days=1),
- )
- result = ResultFactory(country_programme=CountryProgrammeFactory())
- InterventionResultLink.objects.create(
- intervention=intervention,
- cp_output=result,
- )
- self.assertNotEqual(
- intervention.country_programme,
- result.country_programme
- )
-
- self.assertFalse(qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(qs_issue.exists())
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.issues.project_checks.PdOutputsWrongCheck'])
- def test_no_country_programme(self):
- """Check that if intervention has no country programme
- the intervention is ignored during the check
- """
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="pd_outputs_wrong"
- )
- intervention = InterventionFactory()
- result = ResultFactory(country_programme=CountryProgrammeFactory())
- InterventionResultLink.objects.create(
- intervention=intervention,
- cp_output=result,
- )
- self.assertIsNone(intervention.country_programme)
- self.assertNotEqual(
- intervention.country_programme,
- result.country_programme
- )
-
- self.assertFalse(qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(qs_issue.exists())
-
- @override_settings(ISSUE_CHECKS=['etools.applications.management.issues.project_checks.PdOutputsWrongCheck'])
- def test_no_issue(self):
- """Check that valida interventions results in no issue"""
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="pd_outputs_wrong"
- )
- start_date = datetime.date(2001, 1, 1)
- end_date = datetime.date(2001, 12, 31)
- country = CountryProgrammeFactory(
- from_date=start_date,
- to_date=end_date,
- )
- intervention = InterventionFactory(
- country_programme=country,
- start=start_date,
- )
- result = ResultFactory(country_programme=country)
- InterventionResultLink.objects.create(
- intervention=intervention,
- cp_output=result,
- )
- self.assertEqual(
- intervention.country_programme,
- result.country_programme
- )
-
- self.assertFalse(qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(qs_issue.exists())
-
-
-class TestInterventionsAssociatedSSFACheck(BaseTenantTestCase):
- def setUp(self):
- super().setUp()
- self.qs_issue = FlaggedIssue.objects.filter(
- issue_id="interventions_associated_ssfa"
- )
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.issues.project_checks.InterventionsAssociatedSSFACheck'])
- def test_document_type_pd(self):
- """Check that if agreement type SSFA but document type PD
- then issue is raised
- """
- agreement = AgreementFactory(agreement_type=Agreement.SSFA)
- InterventionFactory(
- agreement=agreement,
- document_type=Intervention.PD,
- )
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertTrue(self.qs_issue.exists())
- issue = self.qs_issue.first()
- self.assertIn("type {}".format(Intervention.PD), issue.message)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.issues.project_checks.InterventionsAssociatedSSFACheck'])
- def test_document_type_ssfa(self):
- """Check that if agreement type PCA but document type SSFA
- then issue is raised
- """
- agreement = AgreementFactory(agreement_type=Agreement.PCA)
- InterventionFactory(
- agreement=agreement,
- document_type=Intervention.SSFA,
- )
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertTrue(self.qs_issue.exists())
- issue = self.qs_issue.first()
- self.assertIn("type {}".format(Intervention.SSFA), issue.message)
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.issues.project_checks.InterventionsAssociatedSSFACheck'])
- def test_no_issue_pd(self):
- """Check that if agreement type SSFA and document type PD
- then issue is NOT raised
- """
- agreement = AgreementFactory(agreement_type=Agreement.SSFA)
- InterventionFactory(
- agreement=agreement,
- document_type=Intervention.SSFA,
- )
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(self.qs_issue.exists())
-
- @override_settings(ISSUE_CHECKS=[
- 'etools.applications.management.issues.project_checks.InterventionsAssociatedSSFACheck'])
- def test_no_issue_ssfa(self):
- """Check that if agreement type PCA and document type SSFA
- then issue is NOT raised
- """
- agreement = AgreementFactory(agreement_type=Agreement.PCA)
- InterventionFactory(
- agreement=agreement,
- document_type=Intervention.PD,
- )
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(self.qs_issue.exists())
-
-
-class TestInterventionsAreValidCheck(BaseTenantTestCase):
- def setUp(self):
- super().setUp()
- self.master_user = UserFactory(username="etools_task_admin")
- self.qs_issue = FlaggedIssue.objects.filter(
- issue_id="interventions_are_valid"
- )
-
- def test_invalid_intervention(self):
- """Check if intervention fails validation, issue is raised"""
- intervention = InterventionFactory(
- signed_by_unicef_date=datetime.date(2001, 2, 1),
- signed_by_partner_date=datetime.date(2001, 3, 1),
- signed_pd_document="random.pdf",
- start=datetime.date(2001, 1, 1)
- )
- validator = InterventionValid(intervention, self.master_user)
- self.assertFalse(validator.is_valid)
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertTrue(self.qs_issue.exists())
-
- def test_no_issue(self):
- """Check if intervention does not fail validation,
- no issue is raised
- """
- intervention = InterventionFactory()
- validator = InterventionValid(intervention, self.master_user)
- self.assertTrue(validator.is_valid)
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(self.qs_issue.exists())
-
-
-class TestPDAmendmentsMissingFilesCheck(BaseTenantTestCase):
- def setUp(self):
- super().setUp()
- self.master_user = UserFactory(username="etools_task_admin")
- self.qs_issue = FlaggedIssue.objects.filter(
- issue_id="interventions_amendments_no_file"
- )
-
- def test_no_amendment_file(self):
- """Check that if no amendment file, then issue is raised"""
- amendment = InterventionAmendmentFactory(signed_amendment=None)
- self.assertFalse(amendment.signed_amendment)
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertTrue(self.qs_issue.exists())
- issue = self.qs_issue.first()
- self.assertIn("has missing amendment file", issue.message)
-
- def test_no_issue(self):
- """Check that if amendment file, then issue is NOT raised"""
- amendment = InterventionAmendmentFactory()
- self.assertTrue(amendment.signed_amendment)
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(self.qs_issue.exists())
-
-
-class TestPCAAmendmentsMissingFilesCheck(BaseTenantTestCase):
- def setUp(self):
- super().setUp()
- self.master_user = UserFactory(username="etools_task_admin")
- self.qs_issue = FlaggedIssue.objects.filter(
- issue_id="agreement_amendments_no_file"
- )
-
- def test_no_signed_amendment(self):
- """Check that if agreement has no signed amendment
- then issue is raised
- """
- amendment = AgreementAmendmentFactory(
- signed_amendment=None
- )
- self.assertFalse(amendment.signed_amendment)
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertTrue(self.qs_issue.exists())
- issue = self.qs_issue.first()
- self.assertIn("has missing amendment file", issue.message)
-
- def test_no_issue(self):
- """Check that if agreement has signed amendment
- then issue is NOT raised
- """
- amendment = AgreementAmendmentFactory(signed_amendment="random.pdf")
- self.assertTrue(amendment.signed_amendment)
- self.assertFalse(self.qs_issue.exists())
- checks.bootstrap_checks(default_is_active=True)
- checks.run_all_checks()
- self.assertFalse(self.qs_issue.exists())
diff --git a/src/etools/applications/management/tests/test_models.py b/src/etools/applications/management/tests/test_models.py
deleted file mode 100644
index fd7f1791cd..0000000000
--- a/src/etools/applications/management/tests/test_models.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.management.models import FlaggedIssue
-from etools.applications.management.tests.factories import FlaggedIssueFactory
-from etools.applications.partners.tests.factories import PartnerFactory
-
-
-class TestStrUnicode(BaseTenantTestCase):
- """Ensure calling str() on model instances returns the right text."""
-
- def test_flagged_issue(self):
- partner = PartnerFactory()
- issue = FlaggedIssueFactory(
- content_object=partner,
- issue_id="321",
- message='test message'
- )
- self.assertEqual(str(issue), "test message")
-
- issue = FlaggedIssueFactory(
- content_object=partner,
- issue_id="321",
- message="R\xe4dda Barnen"
- )
- self.assertEqual(str(issue), "R\xe4dda Barnen")
-
-
-class FlaggedIssueTest(BaseTenantTestCase):
-
- @classmethod
- def tearDownClass(cls):
- FlaggedIssue.objects.all().delete()
- super().tearDownClass()
-
- def test_get_or_new_creates_new_unsaved(self):
- partner = PartnerFactory()
- issue = FlaggedIssue.get_or_new(partner, 'test-new-unsaved')
- # make sure we got a new one
- self.assertTrue(issue.pk is None)
-
- def test_get_or_new_returns_saved(self):
- issue_id = 'test-return-saved'
- partner = PartnerFactory()
- issue = FlaggedIssueFactory(
- content_object=partner,
- issue_id=issue_id,
- message='test message'
- )
- self.assertTrue(issue.pk is not None)
- issue_back = FlaggedIssue.get_or_new(partner, issue_id)
- # make sure we got the same one back
- self.assertEqual(issue.pk, issue_back.pk)
diff --git a/src/etools/applications/management/tests/test_tasks.py b/src/etools/applications/management/tests/test_tasks.py
deleted file mode 100644
index 52262e3ef9..0000000000
--- a/src/etools/applications/management/tests/test_tasks.py
+++ /dev/null
@@ -1,35 +0,0 @@
-
-from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.management import tasks
-from etools.applications.management.issues import checks
-from etools.applications.management.models import FlaggedIssue, ISSUE_STATUS_NEW, ISSUE_STATUS_RESOLVED
-from etools.applications.management.tests.factories import FlaggedIssueFactory
-from etools.applications.partners.tests.factories import InterventionAmendmentFactory
-from etools.applications.users.tests.factories import UserFactory
-
-
-class TestRunAllChecksTask(BaseTenantTestCase):
- def test_run_all_checks(self):
- UserFactory(username="etools_task_admin")
- qs_issue = FlaggedIssue.objects.filter(
- issue_id="interventions_amendments_no_file"
- )
- InterventionAmendmentFactory(signed_amendment=None)
- checks.bootstrap_checks(default_is_active=True)
- self.assertFalse(qs_issue.exists())
- tasks.run_all_checks_task()
- self.assertTrue(qs_issue.exists())
-
-
-class TestRecheckAllOpenIssuesTask(BaseTenantTestCase):
- def test_recheck_all_open_issues_task(self):
- UserFactory(username="etools_task_admin")
- amendment = InterventionAmendmentFactory()
- issue = FlaggedIssueFactory(
- content_object=amendment,
- issue_id='interventions_amendments_no_file',
- issue_status=ISSUE_STATUS_NEW,
- )
- tasks.recheck_all_open_issues_task()
- issue_updated = FlaggedIssue.objects.get(pk=issue.pk)
- self.assertEqual(issue_updated.issue_status, ISSUE_STATUS_RESOLVED)
diff --git a/src/etools/applications/management/urls.py b/src/etools/applications/management/urls.py
index 6c27cf9006..a1d0b21234 100644
--- a/src/etools/applications/management/urls.py
+++ b/src/etools/applications/management/urls.py
@@ -3,7 +3,6 @@
from etools.applications.management.views.general import InvalidateCache, SyncCountries, SyncFRs
from etools.applications.management.views.reports import LoadResultStructure
from etools.applications.management.views.tasks_endpoints import (
- FamReportView,
PMPIndicatorsReportView,
SyncDeltaUsers,
TestSendEmailAPIView,
@@ -31,5 +30,4 @@
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'^reports/fam/$', FamReportView.as_view(), name='reports_fam'),
), 'management')
diff --git a/src/etools/applications/management/views/tasks_endpoints.py b/src/etools/applications/management/views/tasks_endpoints.py
index 9f6531748e..7e50b7caab 100644
--- a/src/etools/applications/management/views/tasks_endpoints.py
+++ b/src/etools/applications/management/views/tasks_endpoints.py
@@ -10,7 +10,7 @@
from unicef_restlib.permissions import IsSuperUser
from etools.applications.hact.tasks import update_aggregate_hact_values, update_hact_values
-from etools.applications.management.tasks import fam_report, pmp_indicator_report, send_test_email, user_report
+from etools.applications.management.tasks import pmp_indicator_report, send_test_email, user_report
from etools.libraries.azure_graph_api.tasks import sync_delta_users
@@ -92,8 +92,3 @@ class UsersReportView(BasicReportAPIView):
class PMPIndicatorsReportView(BasicReportAPIView):
report_function = pmp_indicator_report
base_filename = 'pmp_indicators_report'
-
-
-class FamReportView(BasicReportAPIView):
- report_function = fam_report
- base_filename = 'fam_report'
diff --git a/src/etools/applications/management/views/v1.py b/src/etools/applications/management/views/v1.py
index 3c3aef0d20..9ad498c3cf 100644
--- a/src/etools/applications/management/views/v1.py
+++ b/src/etools/applications/management/views/v1.py
@@ -32,11 +32,6 @@ def get_context_data(self, **kwargs):
})
return context
- # def get(self, request):
- # with open(settings.PACKAGE_ROOT + '/templates/frontend/management/management.html', 'r') as my_f:
- # result = my_f.read()
- # return HttpResponse(result)
-
class ActiveUsers(APIView):
"""
From f7253afa52c3fe5e8c7bb19e16ba9e7e2c101d9e Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Tue, 26 Mar 2019 11:18:23 -0400
Subject: [PATCH 42/79] clean issuecheck
---
src/etools/applications/environment/admin.py | 8 +-------
.../migrations/0003_delete_issuecheckconfig.py | 16 ++++++++++++++++
src/etools/applications/environment/models.py | 14 --------------
.../applications/environment/tests/factories.py | 7 -------
.../environment/tests/test_models.py | 12 +-----------
.../applications/environment/tests/test_views.py | 2 +-
.../applications/management/serializers.py | 1 -
.../applications/management/views/gis_v1.py | 4 ++--
8 files changed, 21 insertions(+), 43 deletions(-)
create mode 100644 src/etools/applications/environment/migrations/0003_delete_issuecheckconfig.py
diff --git a/src/etools/applications/environment/admin.py b/src/etools/applications/environment/admin.py
index e3aeb0d38a..5cd2d39eb4 100644
--- a/src/etools/applications/environment/admin.py
+++ b/src/etools/applications/environment/admin.py
@@ -4,13 +4,7 @@
from waffle.admin import FlagAdmin, SwitchAdmin
from waffle.models import Flag, Switch
-from etools.applications.environment.models import IssueCheckConfig, TenantFlag, TenantSwitch
-
-
-@admin.register(IssueCheckConfig)
-class IssueCheckConfigAdmin(admin.ModelAdmin):
- list_display = ['check_id', 'is_active']
- list_filter = ['is_active']
+from etools.applications.environment.models import TenantFlag, TenantSwitch
class TenantFlagAdmin(FlagAdmin):
diff --git a/src/etools/applications/environment/migrations/0003_delete_issuecheckconfig.py b/src/etools/applications/environment/migrations/0003_delete_issuecheckconfig.py
new file mode 100644
index 0000000000..6c7c61dacf
--- /dev/null
+++ b/src/etools/applications/environment/migrations/0003_delete_issuecheckconfig.py
@@ -0,0 +1,16 @@
+# Generated by Django 2.1.7 on 2019-03-26 15:06
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('environment', '0002_auto_20190122_1412'),
+ ]
+
+ operations = [
+ migrations.DeleteModel(
+ name='IssueCheckConfig',
+ ),
+ ]
diff --git a/src/etools/applications/environment/models.py b/src/etools/applications/environment/models.py
index 4a348b1c89..06c76ed0b9 100644
--- a/src/etools/applications/environment/models.py
+++ b/src/etools/applications/environment/models.py
@@ -16,20 +16,6 @@
cache = get_cache()
-class IssueCheckConfig(models.Model):
- """
- Used to enable/disable issue checks at runtime.
- """
- check_id = models.CharField(max_length=100, unique=True, db_index=True, verbose_name=_('Check id'))
- is_active = models.BooleanField(default=False, verbose_name=_('Is Active'))
-
- def __str__(self):
- return '{}: {}'.format(self.check_id, self.is_active)
-
- class Meta:
- verbose_name_plural = _('Issue check config')
-
-
class TenantFlag(BaseModel):
"""
Associate one or more countries with a Flag.
diff --git a/src/etools/applications/environment/tests/factories.py b/src/etools/applications/environment/tests/factories.py
index de8cd974d3..9af375c484 100644
--- a/src/etools/applications/environment/tests/factories.py
+++ b/src/etools/applications/environment/tests/factories.py
@@ -5,13 +5,6 @@
from etools.applications.environment import models
-class IssueCheckConfigFactory(factory.django.DjangoModelFactory):
- class Meta:
- model = models.IssueCheckConfig
-
- check_id = fuzzy.FuzzyText()
-
-
class TenantFlagFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.TenantFlag
diff --git a/src/etools/applications/environment/tests/test_models.py b/src/etools/applications/environment/tests/test_models.py
index 0ce20562ce..0333b71c69 100644
--- a/src/etools/applications/environment/tests/test_models.py
+++ b/src/etools/applications/environment/tests/test_models.py
@@ -4,24 +4,14 @@
from django.test import TestCase
from django.test.utils import override_settings
-
from mock import Mock
from etools.applications.environment.apps import EnvironmentConfig
from etools.applications.environment.helpers import tenant_flag_is_active, tenant_switch_is_active
-from etools.applications.environment.tests.factories import (IssueCheckConfigFactory,
- TenantFlagFactory, TenantSwitchFactory,)
+from etools.applications.environment.tests.factories import TenantFlagFactory, TenantSwitchFactory
from etools.applications.users.tests.factories import CountryFactory, GroupFactory, UserFactory
-class IssueCheckConfigTest(TestCase):
-
- def test_str_method(self):
- issue_check_config = IssueCheckConfigFactory()
- expected = '{}: {}'.format(issue_check_config.check_id, issue_check_config.is_active)
- self.assertEqual(str(issue_check_config), expected)
-
-
class EnvironmentConfigTest(TestCase):
def test_apps(self):
self.assertEqual(apps.get_app_config('environment').name, EnvironmentConfig.name)
diff --git a/src/etools/applications/environment/tests/test_views.py b/src/etools/applications/environment/tests/test_views.py
index 0ba6dfa2a5..c6b054a917 100644
--- a/src/etools/applications/environment/tests/test_views.py
+++ b/src/etools/applications/environment/tests/test_views.py
@@ -1,8 +1,8 @@
import json
-from django.urls import reverse
from django.db import connection
+from django.urls import reverse
from rest_framework import status
diff --git a/src/etools/applications/management/serializers.py b/src/etools/applications/management/serializers.py
index 1b12ab5127..4c31f2ee9d 100644
--- a/src/etools/applications/management/serializers.py
+++ b/src/etools/applications/management/serializers.py
@@ -2,7 +2,6 @@
from rest_framework import serializers
from rest_framework_gis.serializers import GeoFeatureModelSerializer
-
from unicef_locations.models import Location
diff --git a/src/etools/applications/management/views/gis_v1.py b/src/etools/applications/management/views/gis_v1.py
index f620b107b5..575cc7685a 100644
--- a/src/etools/applications/management/views/gis_v1.py
+++ b/src/etools/applications/management/views/gis_v1.py
@@ -5,6 +5,8 @@
from unicef_locations.models import Location
from unicef_restlib.permissions import IsSuperUser
+from etools.applications.action_points.models import ActionPoint
+from etools.applications.activities.models import Activity
from etools.applications.management.serializers import (
GisLocationGeojsonSerializer,
GisLocationListSerializer,
@@ -14,8 +16,6 @@
from etools.applications.reports.models import AppliedIndicator
from etools.applications.t2f.models import TravelActivity
from etools.applications.users.models import Country
-from etools.applications.activities.models import Activity
-from etools.applications.action_points.models import ActionPoint
class GisLocationsInUseViewset(ListAPIView):
From 621c2b7b2792561e1a7d4a187c90ee0d2136320f Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Fri, 12 Apr 2019 11:09:02 -0400
Subject: [PATCH 43/79] remove clone for driver and isort
---
src/etools/applications/t2f/admin.py | 2 +-
src/etools/applications/t2f/helpers/clone_travel.py | 8 --------
.../t2f/migrations/0013_auto_20190103_1345.py | 1 +
src/etools/applications/t2f/models.py | 2 +-
src/etools/applications/t2f/serializers/travel.py | 8 +-------
src/etools/applications/t2f/tests/factories.py | 3 ++-
src/etools/applications/t2f/tests/test_dashboard.py | 5 +----
src/etools/applications/t2f/tests/test_exports.py | 2 +-
.../applications/t2f/tests/test_permission_matrix.py | 10 ++--------
.../applications/t2f/tests/test_travel_details.py | 11 -----------
src/etools/applications/t2f/urls.py | 2 --
src/etools/applications/t2f/views/exports.py | 5 +----
src/etools/applications/t2f/views/travel.py | 8 --------
13 files changed, 11 insertions(+), 56 deletions(-)
diff --git a/src/etools/applications/t2f/admin.py b/src/etools/applications/t2f/admin.py
index c4b0ebc91e..7cae4838e0 100644
--- a/src/etools/applications/t2f/admin.py
+++ b/src/etools/applications/t2f/admin.py
@@ -3,8 +3,8 @@
from etools.applications.action_points.admin import ActionPointAdmin
from etools.applications.publics.admin import AdminListMixin
from etools.applications.t2f import models
-from etools.applications.t2f.models import T2FActionPoint
from etools.applications.t2f.forms import T2FActionPointAdminForm
+from etools.applications.t2f.models import T2FActionPoint
@admin.register(models.Travel)
diff --git a/src/etools/applications/t2f/helpers/clone_travel.py b/src/etools/applications/t2f/helpers/clone_travel.py
index fab6820c09..2b63e23064 100644
--- a/src/etools/applications/t2f/helpers/clone_travel.py
+++ b/src/etools/applications/t2f/helpers/clone_travel.py
@@ -14,14 +14,6 @@ def clone_for_secondary_traveler(self, new_traveler):
return new_travel
- def clone_for_driver(self, new_traveler):
- fk_related = ['itinerary']
- o2o_related = []
- new_travel = self._do_the_cloning(new_traveler, fk_related, o2o_related)
- new_travel.is_driver = True
- new_travel.save()
- return new_travel
-
def _do_the_cloning(self, new_traveler, fk_related, o2o_related):
new_travel = self._clone_model(self.travel)
new_travel.traveler = new_traveler
diff --git a/src/etools/applications/t2f/migrations/0013_auto_20190103_1345.py b/src/etools/applications/t2f/migrations/0013_auto_20190103_1345.py
index 339c24b07f..ec2d08ab10 100644
--- a/src/etools/applications/t2f/migrations/0013_auto_20190103_1345.py
+++ b/src/etools/applications/t2f/migrations/0013_auto_20190103_1345.py
@@ -1,6 +1,7 @@
# Generated by Django 2.0.9 on 2019-01-03 13:45
from django.db import migrations, models
+
import etools.applications.t2f.models
diff --git a/src/etools/applications/t2f/models.py b/src/etools/applications/t2f/models.py
index 060b720d7c..f18c64a28d 100644
--- a/src/etools/applications/t2f/models.py
+++ b/src/etools/applications/t2f/models.py
@@ -16,8 +16,8 @@
from unicef_djangolib.fields import CodedGenericRelation
from unicef_notification.utils import send_notification
-from etools.applications.core.urlresolvers import build_frontend_url
from etools.applications.action_points.models import ActionPoint
+from etools.applications.core.urlresolvers import build_frontend_url
from etools.applications.t2f.serializers.mailing import TravelMailSerializer
from etools.applications.users.models import WorkspaceCounter
diff --git a/src/etools/applications/t2f/serializers/travel.py b/src/etools/applications/t2f/serializers/travel.py
index 983bb27a95..fa07974aeb 100644
--- a/src/etools/applications/t2f/serializers/travel.py
+++ b/src/etools/applications/t2f/serializers/travel.py
@@ -21,13 +21,7 @@
from etools.applications.partners.models import PartnerType
from etools.applications.publics.models import AirlineCompany
from etools.applications.t2f.helpers.permission_matrix import PermissionMatrix
-from etools.applications.t2f.models import (
- ItineraryItem,
- Travel,
- TravelActivity,
- TravelAttachment,
- TravelType,
-)
+from etools.applications.t2f.models import ItineraryItem, Travel, TravelActivity, TravelAttachment, TravelType
itineraryItemSortKey = operator.attrgetter('departure_date')
diff --git a/src/etools/applications/t2f/tests/factories.py b/src/etools/applications/t2f/tests/factories.py
index 057bbe36c0..f14bde4a2f 100644
--- a/src/etools/applications/t2f/tests/factories.py
+++ b/src/etools/applications/t2f/tests/factories.py
@@ -1,15 +1,16 @@
import datetime
+
import factory
from factory import fuzzy
from unicef_locations.tests.factories import LocationFactory
+from etools.applications.action_points.tests.factories import ActionPointFactory
from etools.applications.partners.tests.factories import InterventionFactory
from etools.applications.publics.tests.factories import (
PublicsAirlineCompanyFactory,
PublicsCurrencyFactory,
PublicsDSARegionFactory,
)
-from etools.applications.action_points.tests.factories import ActionPointFactory
from etools.applications.reports.tests.factories import ResultFactory, SectionFactory
from etools.applications.t2f import models
from etools.applications.users.tests.factories import OfficeFactory, UserFactory
diff --git a/src/etools/applications/t2f/tests/test_dashboard.py b/src/etools/applications/t2f/tests/test_dashboard.py
index 6aeb222993..8cfca7a40d 100644
--- a/src/etools/applications/t2f/tests/test_dashboard.py
+++ b/src/etools/applications/t2f/tests/test_dashboard.py
@@ -4,10 +4,7 @@
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import PartnerOrganization
-from etools.applications.publics.tests.factories import (
- PublicsCurrencyFactory,
- PublicsDSARegionFactory,
-)
+from etools.applications.publics.tests.factories import PublicsCurrencyFactory, PublicsDSARegionFactory
from etools.applications.t2f.models import make_travel_reference_number, ModeOfTravel, Travel, TravelType
from etools.applications.t2f.tests.factories import TravelActivityFactory, TravelFactory
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/t2f/tests/test_exports.py b/src/etools/applications/t2f/tests/test_exports.py
index 1ccad3762a..b6a0ff182b 100644
--- a/src/etools/applications/t2f/tests/test_exports.py
+++ b/src/etools/applications/t2f/tests/test_exports.py
@@ -1,6 +1,6 @@
import csv
-import logging
import datetime
+import logging
from django.urls import reverse
from django.utils.six import StringIO
diff --git a/src/etools/applications/t2f/tests/test_permission_matrix.py b/src/etools/applications/t2f/tests/test_permission_matrix.py
index 167f4fab6f..a1caf4a9bc 100644
--- a/src/etools/applications/t2f/tests/test_permission_matrix.py
+++ b/src/etools/applications/t2f/tests/test_permission_matrix.py
@@ -6,15 +6,9 @@
from unicef_locations.tests.factories import LocationFactory
from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.publics.tests.factories import (
- PublicsCurrencyFactory,
- PublicsDSARegionFactory,
-)
+from etools.applications.publics.tests.factories import PublicsCurrencyFactory, PublicsDSARegionFactory
from etools.applications.t2f import UserTypes
-from etools.applications.t2f.helpers.permission_matrix import (
- FakePermissionMatrix,
- get_user_role_list,
-)
+from etools.applications.t2f.helpers.permission_matrix import FakePermissionMatrix, get_user_role_list
from etools.applications.t2f.models import ModeOfTravel, Travel, TravelType
from etools.applications.t2f.tests.factories import TravelFactory
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/t2f/tests/test_travel_details.py b/src/etools/applications/t2f/tests/test_travel_details.py
index 43f2b397ae..491d845b36 100644
--- a/src/etools/applications/t2f/tests/test_travel_details.py
+++ b/src/etools/applications/t2f/tests/test_travel_details.py
@@ -38,7 +38,6 @@ def test_urls(self):
('index', '', {'travel_pk': 1}),
('attachments', 'attachments/', {'travel_pk': 1}),
('attachment_details', 'attachments/1/', {'travel_pk': 1, 'attachment_pk': 1}),
- ('clone_for_driver', 'add_driver/', {'travel_pk': 1}),
('clone_for_secondary_traveler', 'duplicate_travel/', {'travel_pk': 1}),
)
self.assertReversal(names_and_paths, 't2f:travels:details:', '/api/t2f/travels/1/')
@@ -216,16 +215,6 @@ def test_add_attachment(self):
self.assertTrue(attachment_qs.exists())
def test_duplication(self):
- data = {'traveler': self.unicef_staff.id}
- response = self.forced_auth_req('post', reverse('t2f:travels:details:clone_for_driver',
- kwargs={'travel_pk': self.travel.id}),
- data=data, user=self.unicef_staff)
- response_json = json.loads(response.rendered_content)
- self.assertIn('id', response_json)
-
- cloned_travel = Travel.objects.get(id=response_json['id'])
- self.assertNotEqual(cloned_travel.reference_number, self.travel.reference_number)
-
data = {'traveler': self.unicef_staff.id}
response = self.forced_auth_req('post', reverse('t2f:travels:details:clone_for_secondary_traveler',
kwargs={'travel_pk': self.travel.id}),
diff --git a/src/etools/applications/t2f/urls.py b/src/etools/applications/t2f/urls.py
index 9ce135d736..efec97e1ec 100644
--- a/src/etools/applications/t2f/urls.py
+++ b/src/etools/applications/t2f/urls.py
@@ -30,7 +30,6 @@
travel_attachment_details = TravelAttachmentViewSet.as_view({'delete': 'destroy'})
clone_travel_for_secondary_traveler = TravelDetailsViewSet.as_view({'post': 'clone_for_secondary_traveler'})
-clone_travel_for_driver = TravelDetailsViewSet.as_view({'post': 'clone_for_driver'})
action_points_dashboard_list = ActionPointDashboardViewSet.as_view({'get': 'list'})
@@ -42,7 +41,6 @@
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'),
- url(r'^add_driver/$', clone_travel_for_driver, name='clone_for_driver'),
), 'details')
diff --git a/src/etools/applications/t2f/views/exports.py b/src/etools/applications/t2f/views/exports.py
index 43bdaebba7..f05408504d 100644
--- a/src/etools/applications/t2f/views/exports.py
+++ b/src/etools/applications/t2f/views/exports.py
@@ -12,10 +12,7 @@
from etools.applications.core.renderers import FriendlyCSVRenderer
from etools.applications.t2f.filters import travel_list
from etools.applications.t2f.models import ItineraryItem, Travel, TravelActivity
-from etools.applications.t2f.serializers.export import (
- TravelActivityExportSerializer,
- TravelAdminExportSerializer,
-)
+from etools.applications.t2f.serializers.export import TravelActivityExportSerializer, TravelAdminExportSerializer
from etools.applications.t2f.views import T2FPagePagination
diff --git a/src/etools/applications/t2f/views/travel.py b/src/etools/applications/t2f/views/travel.py
index 43df4a16f7..781e5e32d1 100644
--- a/src/etools/applications/t2f/views/travel.py
+++ b/src/etools/applications/t2f/views/travel.py
@@ -107,14 +107,6 @@ def clone_for_secondary_traveler(self, request, *args, **kwargs):
serializer = CloneOutputSerializer(clone, context=self.get_serializer_context())
return Response(serializer.data, status.HTTP_201_CREATED)
- @atomic
- def clone_for_driver(self, request, *args, **kwargs):
- traveler = self._get_traveler_for_cloning()
- helper = CloneTravelHelper(self.get_object())
- clone = helper.clone_for_driver(traveler)
- serializer = CloneOutputSerializer(clone, context=self.get_serializer_context())
- return Response(serializer.data, status.HTTP_201_CREATED)
-
def _get_traveler_for_cloning(self):
parameter_serializer = CloneParameterSerializer(data=self.request.data)
parameter_serializer.is_valid(raise_exception=True)
From ceaf7b5c74069222a0832eca592885a8ea99ebc2 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Fri, 12 Apr 2019 12:14:41 -0400
Subject: [PATCH 44/79] rename sector to section
---
.../action_points/migrations/0001_initial.py | 2 +-
.../migrations/0003_auto_20180518_1610.py | 2 +-
.../applications/action_points/models.py | 2 +-
.../migrations/0002_auto_20180326_1605.py | 4 ++--
.../tests/test_export_intervention.py | 20 ++++++++--------
src/etools/applications/reports/admin.py | 15 +++++++++---
.../reports/migrations/0001_initial.py | 8 +++----
.../migrations/0003_make_not_nullable.py | 6 ++---
.../migrations/0007_auto_20180424_1845.py | 6 ++---
.../migrations/0008_auto_20180515_1744.py | 3 ++-
.../migrations/0014_auto_20181229_0249.py | 1 +
.../migrations/0016_auto_20190412_1612.py | 17 +++++++++++++
src/etools/applications/reports/models.py | 9 +++----
.../applications/reports/tests/test_models.py | 15 ++++++++----
.../reports/tests/test_serializers.py | 24 ++++++++++++-------
.../reports/tests/test_synchronizers.py | 10 +++++---
.../t2f/migrations/0001_initial.py | 2 +-
src/etools/applications/t2f/models.py | 2 +-
.../tpm/migrations/0001_initial.py | 2 +-
src/etools/applications/tpm/models.py | 2 +-
20 files changed, 98 insertions(+), 54 deletions(-)
create mode 100644 src/etools/applications/reports/migrations/0016_auto_20190412_1612.py
diff --git a/src/etools/applications/action_points/migrations/0001_initial.py b/src/etools/applications/action_points/migrations/0001_initial.py
index 7b93d6c581..23d2e78853 100644
--- a/src/etools/applications/action_points/migrations/0001_initial.py
+++ b/src/etools/applications/action_points/migrations/0001_initial.py
@@ -60,7 +60,7 @@ class Migration(migrations.Migration):
('partner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
to='partners.PartnerOrganization', verbose_name='Partner')),
('section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
- to='reports.Sector', verbose_name='Section')),
+ to='reports.Section', verbose_name='Section')),
('tpm_activity', models.ForeignKey(blank=True, null=True,
on_delete=django.db.models.deletion.CASCADE, to='tpm.TPMActivity', verbose_name='TPM Activity')),
('travel_activity', models.ForeignKey(blank=True, null=True,
diff --git a/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py b/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py
index 796210bcbc..f0737cbcdb 100644
--- a/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py
+++ b/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py
@@ -39,6 +39,6 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='actionpoint',
name='section',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='reports.Sector', verbose_name='Section'),
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='reports.Section', verbose_name='Section'),
),
]
diff --git a/src/etools/applications/action_points/models.py b/src/etools/applications/action_points/models.py
index d090b0f40a..70bf651d75 100644
--- a/src/etools/applications/action_points/models.py
+++ b/src/etools/applications/action_points/models.py
@@ -60,7 +60,7 @@ class ActionPoint(TimeStampedModel):
due_date = models.DateField(verbose_name=_('Due Date'), blank=True, null=True)
high_priority = models.BooleanField(default=False, verbose_name=_('High Priority'))
- section = models.ForeignKey('reports.Sector', verbose_name=_('Section'), blank=True, null=True,
+ section = models.ForeignKey('reports.Section', verbose_name=_('Section'), blank=True, null=True,
on_delete=models.CASCADE,
)
office = models.ForeignKey('users.Office', verbose_name=_('Office'), blank=True, null=True,
diff --git a/src/etools/applications/partners/migrations/0002_auto_20180326_1605.py b/src/etools/applications/partners/migrations/0002_auto_20180326_1605.py
index 92b0b55811..556a68b8b7 100644
--- a/src/etools/applications/partners/migrations/0002_auto_20180326_1605.py
+++ b/src/etools/applications/partners/migrations/0002_auto_20180326_1605.py
@@ -23,7 +23,7 @@ class Migration(migrations.Migration):
model_name='interventionsectorlocationlink',
name='sector',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
- related_name='intervention_locations', to='reports.Sector', verbose_name='Sector'),
+ related_name='intervention_locations', to='reports.Section', verbose_name='Sector'),
),
migrations.AddField(
model_name='interventionresultlink',
@@ -118,7 +118,7 @@ class Migration(migrations.Migration):
model_name='intervention',
name='sections',
field=models.ManyToManyField(blank=True, related_name='interventions',
- to='reports.Sector', verbose_name='Sections'),
+ to='reports.Section', verbose_name='Sections'),
),
migrations.AddField(
model_name='intervention',
diff --git a/src/etools/applications/partners/tests/test_export_intervention.py b/src/etools/applications/partners/tests/test_export_intervention.py
index 0beb0e4bf3..74c23c4967 100644
--- a/src/etools/applications/partners/tests/test_export_intervention.py
+++ b/src/etools/applications/partners/tests/test_export_intervention.py
@@ -389,8 +389,8 @@ def test_intervention_location_export(self):
self.intervention.flat_locations.add(LocationFactory(name='Location 0'), LocationFactory(name='Location 1'))
# Some sections
- sec = SectionFactory(name='Sector 0')
- sec1 = SectionFactory(name='Sector 1')
+ sec = SectionFactory(name='Section 0')
+ sec1 = SectionFactory(name='Section 1')
self.intervention.sections.add(sec, sec1)
# Some focal points
@@ -409,8 +409,8 @@ def test_intervention_location_export(self):
self.intervention2 = InterventionFactory(
agreement=AgreementFactory(partner=PartnerFactory(name='Partner 2', vendor_number='123')))
# Sections
- sec2 = SectionFactory(name='Sector 2')
- sec3 = SectionFactory(name='Sector 3')
+ sec2 = SectionFactory(name='Section 2')
+ sec3 = SectionFactory(name='Section 3')
self.intervention2.sections.add(sec2, sec3)
# Results
InterventionResultLinkFactory(
@@ -453,12 +453,12 @@ def test_intervention_location_export(self):
agreement_number_3 = self.intervention3.agreement.agreement_number
self.assertEqual(
f'Partner,Vendor Number,PD Ref Number,Agreement,Status,Location,Section,CP output,Start Date,End Date,Name of UNICEF Focal Point,Hyperlink\r\n'
- f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 0,Sector 0,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
- f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 1,Sector 0,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
- f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 0,Sector 1,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
- f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 1,Sector 1,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
- f'Partner 2,123,{self.intervention2.number},{agreement_number_2},draft,,Sector 2,"Result C, Result D",,,,https://testserver/pmp/interventions/{self.intervention2.id}/details/\r\n'
- f'Partner 2,123,{self.intervention2.number},{agreement_number_2},draft,,Sector 3,"Result C, Result D",,,,https://testserver/pmp/interventions/{self.intervention2.id}/details/\r\n'
+ f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 0,Section 0,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
+ f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 1,Section 0,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
+ f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 0,Section 1,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
+ f'{partner_name},{partner_vendor_code},{self.intervention.number},{agreement_number_1},draft,Location 1,Section 1,"Result A, Result B",2013-01-06,2013-03-20,"Jack Bennie, Phil Silver",https://testserver/pmp/interventions/{self.intervention.id}/details/\r\n'
+ f'Partner 2,123,{self.intervention2.number},{agreement_number_2},draft,,Section 2,"Result C, Result D",,,,https://testserver/pmp/interventions/{self.intervention2.id}/details/\r\n'
+ f'Partner 2,123,{self.intervention2.number},{agreement_number_2},draft,,Section 3,"Result C, Result D",,,,https://testserver/pmp/interventions/{self.intervention2.id}/details/\r\n'
f'Partner 3,456,{self.intervention3.number},{agreement_number_3},draft,Location 2,,Result Fred,,,,https://testserver/pmp/interventions/{self.intervention3.id}/details/\r\n',
result,
)
diff --git a/src/etools/applications/reports/admin.py b/src/etools/applications/reports/admin.py
index 1a3174d8cc..edf942ff7c 100644
--- a/src/etools/applications/reports/admin.py
+++ b/src/etools/applications/reports/admin.py
@@ -5,9 +5,18 @@
from unicef_djangolib.forms import AutoSizeTextForm
from etools.applications.reports.forms import IndicatorAdminForm
-from etools.applications.reports.models import (AppliedIndicator, CountryProgramme, Disaggregation,
- DisaggregationValue, Indicator, IndicatorBlueprint,
- LowerResult, Result, Section, Unit,)
+from etools.applications.reports.models import (
+ AppliedIndicator,
+ CountryProgramme,
+ Disaggregation,
+ DisaggregationValue,
+ Indicator,
+ IndicatorBlueprint,
+ LowerResult,
+ Result,
+ Section,
+ Unit,
+)
class SectionListFilter(admin.SimpleListFilter):
diff --git a/src/etools/applications/reports/migrations/0001_initial.py b/src/etools/applications/reports/migrations/0001_initial.py
index 0f9c1137bb..caae0550b6 100644
--- a/src/etools/applications/reports/migrations/0001_initial.py
+++ b/src/etools/applications/reports/migrations/0001_initial.py
@@ -211,7 +211,7 @@ class Migration(migrations.Migration):
],
),
migrations.CreateModel(
- name='Sector',
+ name='Section',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(
@@ -249,7 +249,7 @@ class Migration(migrations.Migration):
model_name='result',
name='sector',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
- to='reports.Sector', verbose_name='Section'),
+ to='reports.Section', verbose_name='Section'),
),
migrations.AddField(
model_name='indicator',
@@ -261,7 +261,7 @@ class Migration(migrations.Migration):
model_name='indicator',
name='sector',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
- to='reports.Sector', verbose_name='Section'),
+ to='reports.Section', verbose_name='Section'),
),
migrations.AddField(
model_name='indicator',
@@ -297,7 +297,7 @@ class Migration(migrations.Migration):
model_name='appliedindicator',
name='section',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
- to='reports.Sector', verbose_name='Section'),
+ to='reports.Section', verbose_name='Section'),
),
migrations.AlterUniqueTogether(
name='result',
diff --git a/src/etools/applications/reports/migrations/0003_make_not_nullable.py b/src/etools/applications/reports/migrations/0003_make_not_nullable.py
index e8a740e87d..08a0a80550 100644
--- a/src/etools/applications/reports/migrations/0003_make_not_nullable.py
+++ b/src/etools/applications/reports/migrations/0003_make_not_nullable.py
@@ -111,17 +111,17 @@ class Migration(migrations.Migration):
field=models.CharField(blank=True, default='', max_length=10, verbose_name='VISION ID'),
),
migrations.AlterField(
- model_name='sector',
+ model_name='section',
name='alternate_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='Alternate Name'),
),
migrations.AlterField(
- model_name='sector',
+ model_name='section',
name='color',
field=models.CharField(blank=True, default='', max_length=7, verbose_name='Color'),
),
migrations.AlterField(
- model_name='sector',
+ model_name='section',
name='description',
field=models.CharField(blank=True, default='', max_length=256, verbose_name='Description'),
),
diff --git a/src/etools/applications/reports/migrations/0007_auto_20180424_1845.py b/src/etools/applications/reports/migrations/0007_auto_20180424_1845.py
index 735c4c533b..845bb702ac 100644
--- a/src/etools/applications/reports/migrations/0007_auto_20180424_1845.py
+++ b/src/etools/applications/reports/migrations/0007_auto_20180424_1845.py
@@ -106,17 +106,17 @@ class Migration(migrations.Migration):
field=models.CharField(blank=True, max_length=10, null=True, verbose_name='VISION ID'),
),
migrations.AlterField(
- model_name='sector',
+ model_name='section',
name='alternate_name',
field=models.CharField(default='', max_length=255, null=True, verbose_name='Alternate Name'),
),
migrations.AlterField(
- model_name='sector',
+ model_name='section',
name='color',
field=models.CharField(blank=True, max_length=7, null=True, verbose_name='Color'),
),
migrations.AlterField(
- model_name='sector',
+ model_name='section',
name='description',
field=models.CharField(blank=True, max_length=256, null=True, verbose_name='Description'),
),
diff --git a/src/etools/applications/reports/migrations/0008_auto_20180515_1744.py b/src/etools/applications/reports/migrations/0008_auto_20180515_1744.py
index 65d5497608..5035557371 100644
--- a/src/etools/applications/reports/migrations/0008_auto_20180515_1744.py
+++ b/src/etools/applications/reports/migrations/0008_auto_20180515_1744.py
@@ -1,7 +1,8 @@
# Generated by Django 1.10.8 on 2018-05-15 17:44
-from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
+from django.db import migrations, models
+
import model_utils.fields
diff --git a/src/etools/applications/reports/migrations/0014_auto_20181229_0249.py b/src/etools/applications/reports/migrations/0014_auto_20181229_0249.py
index c299687139..c9d428b0a1 100644
--- a/src/etools/applications/reports/migrations/0014_auto_20181229_0249.py
+++ b/src/etools/applications/reports/migrations/0014_auto_20181229_0249.py
@@ -2,6 +2,7 @@
import django.contrib.postgres.fields.jsonb
from django.db import migrations
+
import etools.applications.reports.models
diff --git a/src/etools/applications/reports/migrations/0016_auto_20190412_1612.py b/src/etools/applications/reports/migrations/0016_auto_20190412_1612.py
new file mode 100644
index 0000000000..c5a7a59356
--- /dev/null
+++ b/src/etools/applications/reports/migrations/0016_auto_20190412_1612.py
@@ -0,0 +1,17 @@
+# Generated by Django 2.1.7 on 2019-04-12 16:12
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('reports', '0015_auto_20190208_2042'),
+ ]
+
+ operations = [
+ migrations.AlterModelTable(
+ name='section',
+ table='reports_sector',
+ ),
+ ]
diff --git a/src/etools/applications/reports/models.py b/src/etools/applications/reports/models.py
index f356789ecb..d6e9540adf 100644
--- a/src/etools/applications/reports/models.py
+++ b/src/etools/applications/reports/models.py
@@ -8,7 +8,6 @@
from model_utils.fields import AutoCreatedField, AutoLastModifiedField
from model_utils.models import TimeStampedModel
from mptt.models import MPTTModel, TreeForeignKey
-
from unicef_locations.models import Location
@@ -130,7 +129,7 @@ def __str__(self):
return self.name
-class Sector(TimeStampedModel):
+class Section(TimeStampedModel):
"""
Represents a section
"""
@@ -144,6 +143,7 @@ class Sector(TimeStampedModel):
class Meta:
ordering = ['name']
+ db_table = 'reports_sector'
def __str__(self):
return '{} {}'.format(
@@ -152,9 +152,6 @@ def __str__(self):
)
-Section = Sector
-
-
class ResultManager(models.Manager):
def get_queryset(self):
return super().get_queryset().select_related(
@@ -172,7 +169,7 @@ class Result(MPTTModel):
Represents a result, wbs is unique
Relates to :model:`reports.CountryProgramme`
- Relates to :model:`reports.Sector`
+ Relates to :model:`reports.Section`
Relates to :model:`reports.ResultType`
"""
country_programme = models.ForeignKey(
diff --git a/src/etools/applications/reports/tests/test_models.py b/src/etools/applications/reports/tests/test_models.py
index 87f5ee572a..e3078a355b 100644
--- a/src/etools/applications/reports/tests/test_models.py
+++ b/src/etools/applications/reports/tests/test_models.py
@@ -3,14 +3,21 @@
from django.test import SimpleTestCase
-
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import Agreement
from etools.applications.partners.tests.factories import AgreementFactory
from etools.applications.reports.models import CountryProgramme, Indicator, IndicatorBlueprint, Quarter
-from etools.applications.reports.tests.factories import (CountryProgrammeFactory, IndicatorBlueprintFactory,
- IndicatorFactory, LowerResultFactory, QuarterFactory,
- ResultFactory, ResultTypeFactory, SectionFactory, UnitFactory,)
+from etools.applications.reports.tests.factories import (
+ CountryProgrammeFactory,
+ IndicatorBlueprintFactory,
+ IndicatorFactory,
+ LowerResultFactory,
+ QuarterFactory,
+ ResultFactory,
+ ResultTypeFactory,
+ SectionFactory,
+ UnitFactory,
+)
class TestStrUnicode(SimpleTestCase):
diff --git a/src/etools/applications/reports/tests/test_serializers.py b/src/etools/applications/reports/tests/test_serializers.py
index cc7d0cd5d2..9ca2ae035e 100644
--- a/src/etools/applications/reports/tests/test_serializers.py
+++ b/src/etools/applications/reports/tests/test_serializers.py
@@ -1,20 +1,28 @@
-from django.urls import reverse
from django.test import RequestFactory
+from django.urls import reverse
from rest_framework.exceptions import ValidationError
-
-from etools.applications.core.tests.cases import BaseTenantTestCase
from unicef_locations.tests.factories import LocationFactory
+from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import Intervention
from etools.applications.partners.tests.factories import InterventionFactory, InterventionResultLinkFactory
from etools.applications.reports.models import AppliedIndicator, IndicatorBlueprint, LowerResult
-from etools.applications.reports.serializers.v2 import (AppliedIndicatorSerializer, DisaggregationSerializer,
- LowerResultCUSerializer, LowerResultSimpleCUSerializer,)
-from etools.applications.reports.tests.factories import (AppliedIndicatorFactory, DisaggregationFactory,
- DisaggregationValueFactory, IndicatorBlueprintFactory,
- LowerResultFactory, SectionFactory,)
+from etools.applications.reports.serializers.v2 import (
+ AppliedIndicatorSerializer,
+ DisaggregationSerializer,
+ LowerResultCUSerializer,
+ LowerResultSimpleCUSerializer,
+)
+from etools.applications.reports.tests.factories import (
+ AppliedIndicatorFactory,
+ DisaggregationFactory,
+ DisaggregationValueFactory,
+ IndicatorBlueprintFactory,
+ LowerResultFactory,
+ SectionFactory,
+)
class DisaggregationTest(BaseTenantTestCase):
diff --git a/src/etools/applications/reports/tests/test_synchronizers.py b/src/etools/applications/reports/tests/test_synchronizers.py
index 7dced2291e..a720057cb7 100644
--- a/src/etools/applications/reports/tests/test_synchronizers.py
+++ b/src/etools/applications/reports/tests/test_synchronizers.py
@@ -3,11 +3,15 @@
import json
from etools.applications.core.tests.cases import BaseTenantTestCase
+from etools.applications.reports import synchronizers
from etools.applications.reports.models import CountryProgramme, Indicator, Result, ResultType
-from etools.applications.reports.tests.factories import (CountryProgrammeFactory, IndicatorFactory,
- ResultFactory, ResultTypeFactory,)
+from etools.applications.reports.tests.factories import (
+ CountryProgrammeFactory,
+ IndicatorFactory,
+ ResultFactory,
+ ResultTypeFactory,
+)
from etools.applications.users.models import Country
-from etools.applications.reports import synchronizers
class TestResultStructureSynchronizer(BaseTenantTestCase):
diff --git a/src/etools/applications/t2f/migrations/0001_initial.py b/src/etools/applications/t2f/migrations/0001_initial.py
index f258fda362..a1b3d66c86 100644
--- a/src/etools/applications/t2f/migrations/0001_initial.py
+++ b/src/etools/applications/t2f/migrations/0001_initial.py
@@ -177,7 +177,7 @@ class Migration(migrations.Migration):
('office', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
related_name='+', to='users.Office', verbose_name='Office')),
('sector', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
- related_name='+', to='reports.Sector', verbose_name='Section')),
+ related_name='+', to='reports.Section', verbose_name='Section')),
('supervisor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Supervisor')),
('traveler', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
diff --git a/src/etools/applications/t2f/models.py b/src/etools/applications/t2f/models.py
index 060b720d7c..dc5692a8c5 100644
--- a/src/etools/applications/t2f/models.py
+++ b/src/etools/applications/t2f/models.py
@@ -137,7 +137,7 @@ class Travel(models.Model):
on_delete=models.CASCADE,
)
section = models.ForeignKey(
- 'reports.Sector', null=True, blank=True, related_name='+', verbose_name=_('Section'),
+ 'reports.Section', null=True, blank=True, related_name='+', verbose_name=_('Section'),
on_delete=models.CASCADE,
)
start_date = models.DateField(null=True, blank=True, verbose_name=_('Start Date'))
diff --git a/src/etools/applications/tpm/migrations/0001_initial.py b/src/etools/applications/tpm/migrations/0001_initial.py
index 010cc47c1f..d89fa81faa 100644
--- a/src/etools/applications/tpm/migrations/0001_initial.py
+++ b/src/etools/applications/tpm/migrations/0001_initial.py
@@ -56,7 +56,7 @@ class Migration(migrations.Migration):
('additional_information', models.TextField(blank=True, verbose_name='Additional Information')),
('is_pv', models.BooleanField(default=False, verbose_name='HACT Programmatic Visit')),
('section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
- related_name='tpm_activities', to='reports.Sector', verbose_name='Section')),
+ related_name='tpm_activities', to='reports.Section', verbose_name='Section')),
],
options={
'ordering': ['tpm_visit', 'id'],
diff --git a/src/etools/applications/tpm/models.py b/src/etools/applications/tpm/models.py
index c7491b72b0..88b81e5726 100644
--- a/src/etools/applications/tpm/models.py
+++ b/src/etools/applications/tpm/models.py
@@ -388,7 +388,7 @@ class TPMActivity(Activity):
verbose_name=_('Office(s) of UNICEF Focal Point(s)'))
section = models.ForeignKey(
- 'reports.Sector', related_name='tpm_activities', verbose_name=_('Section'),
+ 'reports.Section', related_name='tpm_activities', verbose_name=_('Section'),
on_delete=models.CASCADE,
)
From f8518bb6cd815a5a2cef57e6379b5f33b69a5fd1 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Thu, 11 Apr 2019 15:56:44 -0400
Subject: [PATCH 45/79] sort
---
Pipfile | 4 ++--
.../action_points/tests/factories.py | 7 +++---
.../applications/tpm/tests/factories.py | 2 +-
src/etools/applications/users/admin.py | 1 +
.../migrations/0001_squashed_0007_user.py | 6 +++--
.../migrations/0008_auto_20190111_1525.py | 3 ++-
src/etools/applications/users/models.py | 1 +
.../applications/users/tests/factories.py | 2 +-
.../applications/users/tests/test_csrf.py | 2 +-
.../applications/users/tests/test_views.py | 13 ----------
src/etools/applications/users/urls.py | 9 +------
src/etools/applications/users/urls_v2.py | 11 ++++++---
src/etools/applications/users/urls_v3.py | 9 +++++--
src/etools/applications/users/views.py | 11 ---------
src/etools/applications/users/views_v2.py | 4 ----
.../utils/common/tests/factories.py | 24 -------------------
src/etools/config/urls.py | 21 ++++++++--------
src/etools/libraries/tests/factories.py | 24 +++++++++++++++++++
18 files changed, 67 insertions(+), 87 deletions(-)
delete mode 100644 src/etools/applications/utils/common/tests/factories.py
diff --git a/Pipfile b/Pipfile
index cf13ddc4fb..29ff0284d1 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,6 +4,7 @@ url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
+django-debug-toolbar = "==1.11"
flake8 = "*"
coverage = "*"
mock = "*"
@@ -15,7 +16,6 @@ pdbpp = "*"
tox = "*"
drf-api-checker = "*"
factory-boy = ">=2.11"
-django-extensions = "*"
sphinx = "*"
[packages]
@@ -31,7 +31,7 @@ django-celery-email = "==2.0.1"
django_celery_results = "==1.0.4"
django-contrib-comments = "==1.9.1"
django-cors-headers = "==2.5"
-django-debug-toolbar = "==1.11"
+django-extensions = "==2.1.6"
django-easy-pdf = "==0.1.1"
django-filter = "==2.1"
django-fsm = "==2.6"
diff --git a/src/etools/applications/action_points/tests/factories.py b/src/etools/applications/action_points/tests/factories.py
index b892848d93..2bc3e57f7d 100644
--- a/src/etools/applications/action_points/tests/factories.py
+++ b/src/etools/applications/action_points/tests/factories.py
@@ -4,16 +4,15 @@
import factory.fuzzy
from django_comments.models import Comment
-
-from etools.applications.action_points.models import ActionPoint
-from etools.applications.action_points.categories.models import Category
from unicef_locations.tests.factories import LocationFactory
+from etools.applications.action_points.categories.models import Category
+from etools.applications.action_points.models import ActionPoint
from etools.applications.partners.tests.factories import InterventionFactory, ResultFactory
from etools.applications.reports.tests.factories import SectionFactory
from etools.applications.users.tests.factories import UserFactory
-from etools.applications.utils.common.tests.factories import StatusFactoryMetaClass
from etools.libraries.djangolib.utils import get_current_site
+from etools.libraries.tests.factories import StatusFactoryMetaClass
class ActionPointCommentFactory(factory.DjangoModelFactory):
diff --git a/src/etools/applications/tpm/tests/factories.py b/src/etools/applications/tpm/tests/factories.py
index 2842f523d2..d7a2b1a512 100644
--- a/src/etools/applications/tpm/tests/factories.py
+++ b/src/etools/applications/tpm/tests/factories.py
@@ -16,7 +16,7 @@
from etools.applications.tpm.models import TPMActivity, TPMVisit, TPMVisitReportRejectComment
from etools.applications.tpm.tpmpartners.models import TPMPartner, TPMPartnerStaffMember
from etools.applications.users.tests.factories import OfficeFactory as SimpleOfficeFactory, PMEUserFactory, UserFactory
-from etools.applications.utils.common.tests.factories import StatusFactoryMetaClass
+from etools.libraries.tests.factories import StatusFactoryMetaClass
_FUZZY_START_DATE = timezone.now().date() - datetime.timedelta(days=5)
_FUZZY_END_DATE = timezone.now().date() + datetime.timedelta(days=5)
diff --git a/src/etools/applications/users/admin.py b/src/etools/applications/users/admin.py
index 80e88e27c8..3204577354 100644
--- a/src/etools/applications/users/admin.py
+++ b/src/etools/applications/users/admin.py
@@ -7,6 +7,7 @@
from django.http.response import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
+
from django_tenants.utils import get_public_schema_name
from etools.applications.hact.tasks import update_hact_for_country, update_hact_values
diff --git a/src/etools/applications/users/migrations/0001_squashed_0007_user.py b/src/etools/applications/users/migrations/0001_squashed_0007_user.py
index 0075b951e1..228c72fc60 100644
--- a/src/etools/applications/users/migrations/0001_squashed_0007_user.py
+++ b/src/etools/applications/users/migrations/0001_squashed_0007_user.py
@@ -2,12 +2,14 @@
from __future__ import unicode_literals
from decimal import Decimal
-from django.conf import settings
+
import django.contrib.auth.models
import django.core.validators
-from django.db import migrations, models
import django.db.migrations.operations.special
import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
import django_tenants.postgresql_backend.base
diff --git a/src/etools/applications/users/migrations/0008_auto_20190111_1525.py b/src/etools/applications/users/migrations/0008_auto_20190111_1525.py
index d1663e7c7d..8b774727b3 100644
--- a/src/etools/applications/users/migrations/0008_auto_20190111_1525.py
+++ b/src/etools/applications/users/migrations/0008_auto_20190111_1525.py
@@ -1,7 +1,8 @@
# Generated by Django 2.0.9 on 2019-01-11 15:25
-from django.db import migrations
import django.utils.timezone
+from django.db import migrations
+
import model_utils.fields
diff --git a/src/etools/applications/users/models.py b/src/etools/applications/users/models.py
index 3d5708a19e..052c50c40b 100644
--- a/src/etools/applications/users/models.py
+++ b/src/etools/applications/users/models.py
@@ -9,6 +9,7 @@
from django.db.models.signals import post_save
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
+
from django_tenants.models import TenantMixin
from model_utils.models import TimeStampedModel
diff --git a/src/etools/applications/users/tests/factories.py b/src/etools/applications/users/tests/factories.py
index 588b8e3430..d921433f9a 100644
--- a/src/etools/applications/users/tests/factories.py
+++ b/src/etools/applications/users/tests/factories.py
@@ -7,8 +7,8 @@
from factory.fuzzy import FuzzyText
from etools.applications.core.tests.cases import SCHEMA_NAME
-from etools.applications.users import models
from etools.applications.publics.tests.factories import PublicsCurrencyFactory
+from etools.applications.users import models
class GroupFactory(factory.django.DjangoModelFactory):
diff --git a/src/etools/applications/users/tests/test_csrf.py b/src/etools/applications/users/tests/test_csrf.py
index 794d3e1076..e71dec744d 100644
--- a/src/etools/applications/users/tests/test_csrf.py
+++ b/src/etools/applications/users/tests/test_csrf.py
@@ -1,5 +1,5 @@
-from django.urls import reverse
from django.test import Client, TestCase
+from django.urls import reverse
from rest_framework import status
diff --git a/src/etools/applications/users/tests/test_views.py b/src/etools/applications/users/tests/test_views.py
index 4132aa319b..39037fb28a 100644
--- a/src/etools/applications/users/tests/test_views.py
+++ b/src/etools/applications/users/tests/test_views.py
@@ -1,4 +1,3 @@
-
import json
from operator import itemgetter
from unittest import skip
@@ -15,18 +14,6 @@
from etools.applications.users.tests.factories import CountryFactory, GroupFactory, OfficeFactory, UserFactory
-class TestUserAuthAPIView(BaseTenantTestCase):
- def test_get(self):
- self.user = UserFactory()
- response = self.forced_auth_req(
- "get",
- reverse("users:user-api-profile"),
- user=self.user
- )
- self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(response.data["id"], self.user.pk)
-
-
class TestChangeUserCountry(BaseTenantTestCase):
@classmethod
def setUpTestData(cls):
diff --git a/src/etools/applications/users/urls.py b/src/etools/applications/users/urls.py
index f3adc4cba5..1d2899454f 100644
--- a/src/etools/applications/users/urls.py
+++ b/src/etools/applications/users/urls.py
@@ -1,17 +1,10 @@
from django.conf.urls import url
-from etools.applications.users.views import (
- ChangeUserCountryView,
- MyProfileAPIView,
- StaffUsersView,
- UserAuthAPIView,
- UsersDetailAPIView,
-)
+from etools.applications.users.views import ChangeUserCountryView, MyProfileAPIView, StaffUsersView, UsersDetailAPIView
app_name = 'users'
urlpatterns = (
# api
- url(r'^api/profile/$', UserAuthAPIView.as_view(), name="user-api-profile"),
url(r'^api/changecountry/$', ChangeUserCountryView.as_view(), name="country-change"),
url(r'^api/$', StaffUsersView.as_view()),
url(r'^api/(?P\d+)/$', UsersDetailAPIView.as_view(http_method_names=['get']), name="user-detail"),
diff --git a/src/etools/applications/users/urls_v2.py b/src/etools/applications/users/urls_v2.py
index 6103edf90c..6e5c761a77 100644
--- a/src/etools/applications/users/urls_v2.py
+++ b/src/etools/applications/users/urls_v2.py
@@ -1,11 +1,16 @@
from django.conf.urls import url
-from etools.applications.users.views_v2 import (ChangeUserCountryView, CountriesViewSet, CountryView, MyProfileAPIView,
- StaffUsersView, UserAuthAPIView, UsersDetailAPIView,)
+from etools.applications.users.views_v2 import (
+ ChangeUserCountryView,
+ CountriesViewSet,
+ CountryView,
+ MyProfileAPIView,
+ StaffUsersView,
+ UsersDetailAPIView,
+)
app_name = 'users'
urlpatterns = (
- url(r'^profile/$', UserAuthAPIView.as_view()),
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"),
diff --git a/src/etools/applications/users/urls_v3.py b/src/etools/applications/users/urls_v3.py
index 7f50e8d844..b08450320d 100644
--- a/src/etools/applications/users/urls_v3.py
+++ b/src/etools/applications/users/urls_v3.py
@@ -1,8 +1,13 @@
from django.conf.urls import url
from etools.applications.users.views import ADUserAPIView
-from etools.applications.users.views_v3 import (ChangeUserCountryView, CountryView, MyProfileAPIView,
- UsersDetailAPIView, UsersListAPIView,)
+from etools.applications.users.views_v3 import (
+ ChangeUserCountryView,
+ CountryView,
+ MyProfileAPIView,
+ UsersDetailAPIView,
+ UsersListAPIView,
+)
app_name = 'users'
urlpatterns = (
diff --git a/src/etools/applications/users/views.py b/src/etools/applications/users/views.py
index ea9cb92e58..0acb72e0a3 100644
--- a/src/etools/applications/users/views.py
+++ b/src/etools/applications/users/views.py
@@ -26,23 +26,12 @@
SimpleProfileSerializer,
SimpleUserSerializer,
UserCreationSerializer,
- UserSerializer,
)
from etools.libraries.azure_graph_api.tasks import retrieve_user_info
logger = logging.getLogger(__name__)
-class UserAuthAPIView(RetrieveAPIView):
- # TODO: Consider removing now use JWT
- model = get_user_model()
- serializer_class = UserSerializer
-
- def get_object(self, queryset=None, **kwargs):
- user = self.request.user
- return user
-
-
class ADUserAPIView(DetailView):
template_name = 'admin/users/user/api.html'
model = get_user_model()
diff --git a/src/etools/applications/users/views_v2.py b/src/etools/applications/users/views_v2.py
index 97915da8ff..52013a0fe0 100644
--- a/src/etools/applications/users/views_v2.py
+++ b/src/etools/applications/users/views_v2.py
@@ -9,10 +9,6 @@
logger = logging.getLogger(__name__)
-class UserAuthAPIView(v1.UserAuthAPIView):
- """Stub for UserAuthAPIView"""
-
-
class ChangeUserCountryView(v1.ChangeUserCountryView):
"""Stub for ChangeUserCountryView"""
diff --git a/src/etools/applications/utils/common/tests/factories.py b/src/etools/applications/utils/common/tests/factories.py
deleted file mode 100644
index 0f1e4f8818..0000000000
--- a/src/etools/applications/utils/common/tests/factories.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from factory.base import FactoryMetaClass
-
-
-class StatusFactoryMetaClass(FactoryMetaClass):
- """
- Factory metaclass to generate object in correct status with dependent attributes.
- When new object is generated, metaclass check for corresponding factory in provided status_factories
- and if found, generate instance using it.
- """
-
- def __call__(cls, **kwargs):
- status = kwargs.pop('status', None)
- factory = cls._status_factories.get(status)
- if factory:
- return factory(**kwargs)
-
- return super().__call__(**kwargs)
-
- def __new__(mcs, class_name, bases, attrs):
- # hide status_factories property to avoid it being consumed by model.create
- status_factories = attrs.pop('status_factories', {})
- new_class = super().__new__(mcs, class_name, bases, attrs)
- new_class._status_factories = status_factories
- return new_class
diff --git a/src/etools/config/urls.py b/src/etools/config/urls.py
index 87045cdf3a..fc1748da6c 100644
--- a/src/etools/config/urls.py
+++ b/src/etools/config/urls.py
@@ -7,17 +7,19 @@
from rest_framework_nested import routers
from rest_framework_swagger.renderers import OpenAPIRenderer
-from etools.applications.core.views import (
- IssueJWTRedirectView,
- logout_view,
- MainView,
-)
+from etools.applications.core.schemas import get_schema_view, get_swagger_view
+from etools.applications.core.views import IssueJWTRedirectView, logout_view, MainView
from etools.applications.management.urls import urlpatterns as management_urls
from etools.applications.partners.views.v1 import FileTypeViewSet
from etools.applications.publics import urls as publics_patterns
from etools.applications.publics.views import StaticDataView
-from etools.applications.reports.views.v1 import IndicatorViewSet, ResultTypeViewSet, ResultViewSet, UnitViewSet, \
- SectionViewSet
+from etools.applications.reports.views.v1 import (
+ IndicatorViewSet,
+ ResultTypeViewSet,
+ ResultViewSet,
+ SectionViewSet,
+ UnitViewSet,
+)
from etools.applications.t2f.urls import urlpatterns as t2f_patterns
from etools.applications.users.views import (
CountriesViewSet,
@@ -26,7 +28,8 @@
OfficeViewSet,
UserViewSet,
)
-from etools.applications.core.schemas import get_schema_view, get_swagger_view
+# these imports are used to autodiscover admin forms located outside of INSTALLED_APPS(the libraries folder for example)
+from etools.libraries.locations import admin as locations_admin # noqa: ignore=F401
from etools.libraries.locations.views import (
CartoDBTablesView,
LocationQuerySetView,
@@ -34,8 +37,6 @@
LocationsViewSet,
LocationTypesViewSet,
)
-# these imports are used to autodiscover admin forms located outside of INSTALLED_APPS(the libraries folder for example)
-from etools.libraries.locations import admin as locations_admin # noqa: ignore=F401
# ****************** API docs and schemas ******************************
schema_view = get_swagger_view(title='eTools API')
diff --git a/src/etools/libraries/tests/factories.py b/src/etools/libraries/tests/factories.py
index 626ba3102c..6673aaf4ea 100644
--- a/src/etools/libraries/tests/factories.py
+++ b/src/etools/libraries/tests/factories.py
@@ -1,4 +1,5 @@
import factory
+from factory.base import FactoryMetaClass
class InheritedTrait(factory.Trait):
@@ -11,3 +12,26 @@ def __init__(self, *parents, **kwargs):
overrides.update(kwargs)
super().__init__(**overrides)
+
+
+class StatusFactoryMetaClass(FactoryMetaClass):
+ """
+ Factory metaclass to generate object in correct status with dependent attributes.
+ When new object is generated, metaclass check for corresponding factory in provided status_factories
+ and if found, generate instance using it.
+ """
+
+ def __call__(cls, **kwargs):
+ status = kwargs.pop('status', None)
+ factory = cls._status_factories.get(status)
+ if factory:
+ return factory(**kwargs)
+
+ return super().__call__(**kwargs)
+
+ def __new__(mcs, class_name, bases, attrs):
+ # hide status_factories property to avoid it being consumed by model.create
+ status_factories = attrs.pop('status_factories', {})
+ new_class = super().__new__(mcs, class_name, bases, attrs)
+ new_class._status_factories = status_factories
+ return new_class
From 21c8a00ca67131a1cc67617b6c9d5f6510406a49 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Mon, 15 Apr 2019 10:06:10 -0400
Subject: [PATCH 46/79] visit export amend
---
src/etools/applications/tpm/admin.py | 2 +-
src/etools/applications/tpm/export/serializers.py | 1 +
.../applications/tpm/migrations/0005_tpmvisit_author.py | 2 +-
.../applications/tpm/migrations/0006_auto_20180522_0736.py | 1 -
src/etools/applications/tpm/serializers/attachments.py | 1 +
src/etools/applications/tpm/tests/base.py | 2 +-
src/etools/applications/tpm/tests/test_transitions.py | 4 ++--
src/etools/applications/tpm/views.py | 2 +-
8 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/etools/applications/tpm/admin.py b/src/etools/applications/tpm/admin.py
index f0e9b08b62..3fc12e4907 100644
--- a/src/etools/applications/tpm/admin.py
+++ b/src/etools/applications/tpm/admin.py
@@ -1,7 +1,7 @@
from django.contrib import admin
from etools.applications.publics.admin import AdminListMixin
-from etools.applications.tpm import models, forms
+from etools.applications.tpm import forms, models
@admin.register(models.TPMActivity)
diff --git a/src/etools/applications/tpm/export/serializers.py b/src/etools/applications/tpm/export/serializers.py
index 7f6e7cd5ab..325e72fb72 100644
--- a/src/etools/applications/tpm/export/serializers.py
+++ b/src/etools/applications/tpm/export/serializers.py
@@ -98,6 +98,7 @@ class TPMVisitExportSerializer(serializers.Serializer):
report_link = serializers.SerializerMethodField()
attachments = serializers.SerializerMethodField()
additional_information = CommaSeparatedExportField(source='tpm_activities.additional_information', allow_null=True)
+ visit_information = serializers.CharField()
link = serializers.CharField(source='get_object_url')
def get_report_link(self, obj):
diff --git a/src/etools/applications/tpm/migrations/0005_tpmvisit_author.py b/src/etools/applications/tpm/migrations/0005_tpmvisit_author.py
index 0f3208ddd1..62a993e583 100644
--- a/src/etools/applications/tpm/migrations/0005_tpmvisit_author.py
+++ b/src/etools/applications/tpm/migrations/0005_tpmvisit_author.py
@@ -1,7 +1,7 @@
# Generated by Django 1.10.8 on 2018-05-21 14:22
+import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
-import django.db.models.deletion
class Migration(migrations.Migration):
diff --git a/src/etools/applications/tpm/migrations/0006_auto_20180522_0736.py b/src/etools/applications/tpm/migrations/0006_auto_20180522_0736.py
index bbcc144238..c7f8b9f499 100644
--- a/src/etools/applications/tpm/migrations/0006_auto_20180522_0736.py
+++ b/src/etools/applications/tpm/migrations/0006_auto_20180522_0736.py
@@ -3,7 +3,6 @@
from django.db import migrations
-
# tpm action point, action point
statuses_mapping = {
'open': 'open',
diff --git a/src/etools/applications/tpm/serializers/attachments.py b/src/etools/applications/tpm/serializers/attachments.py
index e923291f41..ecded34f22 100644
--- a/src/etools/applications/tpm/serializers/attachments.py
+++ b/src/etools/applications/tpm/serializers/attachments.py
@@ -4,6 +4,7 @@
from unicef_attachments.fields import FileTypeModelChoiceField
from unicef_attachments.models import AttachmentLink, FileType
from unicef_attachments.serializers import AttachmentLinkSerializer, BaseAttachmentSerializer
+
from etools.applications.attachments.utils import get_file_type
diff --git a/src/etools/applications/tpm/tests/base.py b/src/etools/applications/tpm/tests/base.py
index feaf9c66a2..2615ee5944 100644
--- a/src/etools/applications/tpm/tests/base.py
+++ b/src/etools/applications/tpm/tests/base.py
@@ -1,7 +1,7 @@
from django.core.management import call_command
from etools.applications.tpm.tests.factories import TPMPartnerFactory, TPMUserFactory
-from etools.applications.users.tests.factories import UserFactory, PMEUserFactory
+from etools.applications.users.tests.factories import PMEUserFactory, UserFactory
from etools.libraries.djangolib.models import GroupWrapper
diff --git a/src/etools/applications/tpm/tests/test_transitions.py b/src/etools/applications/tpm/tests/test_transitions.py
index ccec41ea87..fe2d54f6dc 100644
--- a/src/etools/applications/tpm/tests/test_transitions.py
+++ b/src/etools/applications/tpm/tests/test_transitions.py
@@ -6,10 +6,10 @@
from rest_framework import status
from etools.applications.core.tests.cases import BaseTenantTestCase
+from etools.applications.permissions2.tests.mixins import TransitionPermissionsTestCaseMixin
from etools.applications.tpm.models import TPMVisit
from etools.applications.tpm.tests.base import TPMTestCaseMixin
-from etools.applications.tpm.tests.factories import TPMVisitFactory, TPMUserFactory
-from etools.applications.permissions2.tests.mixins import TransitionPermissionsTestCaseMixin
+from etools.applications.tpm.tests.factories import TPMUserFactory, TPMVisitFactory
from etools.applications.users.tests.factories import PMEUserFactory, UserFactory
diff --git a/src/etools/applications/tpm/views.py b/src/etools/applications/tpm/views.py
index 2a737e762a..30be67df70 100644
--- a/src/etools/applications/tpm/views.py
+++ b/src/etools/applications/tpm/views.py
@@ -61,8 +61,8 @@
TPMActivityAttachmentLinkSerializer,
TPMAttachmentLinkSerializer,
TPMPartnerAttachmentsSerializer,
- TPMVisitAttachmentsSerializer,
TPMVisitAttachmentLinkSerializer,
+ TPMVisitAttachmentsSerializer,
TPMVisitReportAttachmentsSerializer,
)
from etools.applications.tpm.serializers.partner import (
From 63477d8c33d2ddb7d9c7686ab95ed60b144e4643 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Fri, 12 Apr 2019 13:35:55 -0400
Subject: [PATCH 47/79] 11091
---
.../categories/migrations/0001_initial.py | 3 +-
.../update_action_points_permissions.py | 9 ++++--
.../migrations/0002_auto_20180518_0835.py | 2 +-
.../migrations/0003_auto_20180518_1610.py | 3 +-
.../migrations/0004_auto_20180521_1052.py | 2 +-
.../migrations/0005_auto_20180713_0805.py | 2 +-
.../migrations/0006_auto_20180718_1439.py | 2 +-
.../migrations/0007_auto_20180731_0920.py | 2 +-
.../applications/action_points/models.py | 4 +--
.../action_points/tests/factories.py | 5 ++--
src/etools/applications/audit/forms.py | 1 +
.../commands/update_audit_permissions.py | 23 +++++++++++----
.../migrations/0009_auto_20180521_1052.py | 1 -
.../migrations/0015_auto_20190312_2010.py | 2 +-
.../migrations/0016_auto_20190328_1528.py | 1 +
.../audit/purchase_order/admin.py | 8 +++--
.../migrations/0002_fix_null_values.py | 1 +
.../audit/purchase_order/tests/test_tasks.py | 2 +-
.../applications/audit/serializers/export.py | 5 +---
src/etools/applications/audit/tests/base.py | 6 ++--
.../applications/audit/tests/factories.py | 29 +++++++++++++++----
.../applications/audit/tests/test_email.py | 2 +-
.../applications/audit/tests/test_models.py | 23 ++++++++++-----
.../applications/audit/tests/test_views.py | 3 +-
src/etools/applications/tpm/filters.py | 1 +
25 files changed, 96 insertions(+), 46 deletions(-)
diff --git a/src/etools/applications/action_points/categories/migrations/0001_initial.py b/src/etools/applications/action_points/categories/migrations/0001_initial.py
index b8578ae97d..86038b7287 100644
--- a/src/etools/applications/action_points/categories/migrations/0001_initial.py
+++ b/src/etools/applications/action_points/categories/migrations/0001_initial.py
@@ -2,9 +2,10 @@
from __future__ import unicode_literals
import django.utils.timezone
-import model_utils.fields
from django.db import migrations, models
+import model_utils.fields
+
class Migration(migrations.Migration):
diff --git a/src/etools/applications/action_points/management/commands/update_action_points_permissions.py b/src/etools/applications/action_points/management/commands/update_action_points_permissions.py
index b2b3f55f61..bf579ad193 100644
--- a/src/etools/applications/action_points/management/commands/update_action_points_permissions.py
+++ b/src/etools/applications/action_points/management/commands/update_action_points_permissions.py
@@ -1,8 +1,13 @@
from django.core.management import BaseCommand
from etools.applications.action_points.conditions import (
- ActionPointAssignedByCondition, ActionPointAssigneeCondition, ActionPointAuthorCondition,
- ActionPointModuleCondition, RelatedActionPointCondition, UnRelatedActionPointCondition)
+ ActionPointAssignedByCondition,
+ ActionPointAssigneeCondition,
+ ActionPointAuthorCondition,
+ ActionPointModuleCondition,
+ RelatedActionPointCondition,
+ UnRelatedActionPointCondition,
+)
from etools.applications.action_points.models import ActionPoint, PME, UNICEFUser
from etools.applications.permissions2.conditions import GroupCondition, NewObjectCondition, ObjectStatusCondition
from etools.applications.permissions2.models import Permission
diff --git a/src/etools/applications/action_points/migrations/0002_auto_20180518_0835.py b/src/etools/applications/action_points/migrations/0002_auto_20180518_0835.py
index 1a5ddf8e38..a1efa9389b 100644
--- a/src/etools/applications/action_points/migrations/0002_auto_20180518_0835.py
+++ b/src/etools/applications/action_points/migrations/0002_auto_20180518_0835.py
@@ -1,6 +1,6 @@
# Generated by Django 1.10.8 on 2018-05-18 08:35
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py b/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py
index 796210bcbc..4786cf1b25 100644
--- a/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py
+++ b/src/etools/applications/action_points/migrations/0003_auto_20180518_1610.py
@@ -1,8 +1,9 @@
# Generated by Django 1.10.8 on 2018-05-18 16:10
from __future__ import unicode_literals
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
+
import model_utils.fields
diff --git a/src/etools/applications/action_points/migrations/0004_auto_20180521_1052.py b/src/etools/applications/action_points/migrations/0004_auto_20180521_1052.py
index 3d3678fbcb..231b235ef7 100644
--- a/src/etools/applications/action_points/migrations/0004_auto_20180521_1052.py
+++ b/src/etools/applications/action_points/migrations/0004_auto_20180521_1052.py
@@ -1,8 +1,8 @@
# Generated by Django 1.10.8 on 2018-05-21 10:52
from __future__ import unicode_literals
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/src/etools/applications/action_points/migrations/0005_auto_20180713_0805.py b/src/etools/applications/action_points/migrations/0005_auto_20180713_0805.py
index 3b56209ea8..6712dd1011 100644
--- a/src/etools/applications/action_points/migrations/0005_auto_20180713_0805.py
+++ b/src/etools/applications/action_points/migrations/0005_auto_20180713_0805.py
@@ -1,8 +1,8 @@
# Generated by Django 1.10.8 on 2018-07-13 08:05
from __future__ import unicode_literals
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/src/etools/applications/action_points/migrations/0006_auto_20180718_1439.py b/src/etools/applications/action_points/migrations/0006_auto_20180718_1439.py
index fb55a58cb7..ae87350ab3 100644
--- a/src/etools/applications/action_points/migrations/0006_auto_20180718_1439.py
+++ b/src/etools/applications/action_points/migrations/0006_auto_20180718_1439.py
@@ -1,8 +1,8 @@
# Generated by Django 1.10.8 on 2018-07-18 14:39
from __future__ import unicode_literals
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/src/etools/applications/action_points/migrations/0007_auto_20180731_0920.py b/src/etools/applications/action_points/migrations/0007_auto_20180731_0920.py
index d238873856..c4d95823fb 100644
--- a/src/etools/applications/action_points/migrations/0007_auto_20180731_0920.py
+++ b/src/etools/applications/action_points/migrations/0007_auto_20180731_0920.py
@@ -1,8 +1,8 @@
# Generated by Django 1.10.8 on 2018-07-31 09:20
from __future__ import unicode_literals
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
def copy_categories(apps, schema_editor):
diff --git a/src/etools/applications/action_points/models.py b/src/etools/applications/action_points/models.py
index d090b0f40a..28532c599e 100644
--- a/src/etools/applications/action_points/models.py
+++ b/src/etools/applications/action_points/models.py
@@ -11,13 +11,13 @@
from unicef_notification.models import Notification
from unicef_snapshot.models import Activity
-from etools.applications.core.urlresolvers import build_frontend_url
from etools.applications.action_points.categories.models import Category
from etools.applications.action_points.transitions.conditions import ActionPointCompleteActionsTakenCheck
from etools.applications.action_points.transitions.serializers.serializers import ActionPointCompleteSerializer
+from etools.applications.core.urlresolvers import build_frontend_url
+from etools.libraries.djangolib.models import GroupWrapper
from etools.libraries.djangolib.utils import get_environment
from etools.libraries.fsm.views import has_action_permission
-from etools.libraries.djangolib.models import GroupWrapper
class ActionPoint(TimeStampedModel):
diff --git a/src/etools/applications/action_points/tests/factories.py b/src/etools/applications/action_points/tests/factories.py
index b892848d93..575c100f20 100644
--- a/src/etools/applications/action_points/tests/factories.py
+++ b/src/etools/applications/action_points/tests/factories.py
@@ -4,11 +4,10 @@
import factory.fuzzy
from django_comments.models import Comment
-
-from etools.applications.action_points.models import ActionPoint
-from etools.applications.action_points.categories.models import Category
from unicef_locations.tests.factories import LocationFactory
+from etools.applications.action_points.categories.models import Category
+from etools.applications.action_points.models import ActionPoint
from etools.applications.partners.tests.factories import InterventionFactory, ResultFactory
from etools.applications.reports.tests.factories import SectionFactory
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/audit/forms.py b/src/etools/applications/audit/forms.py
index 1309443684..5a7b8288a6 100644
--- a/src/etools/applications/audit/forms.py
+++ b/src/etools/applications/audit/forms.py
@@ -1,4 +1,5 @@
from django import forms
+
from etools.applications.audit.models import EngagementActionPoint
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 ae21cd00e1..9119003121 100644
--- a/src/etools/applications/audit/management/commands/update_audit_permissions.py
+++ b/src/etools/applications/audit/management/commands/update_audit_permissions.py
@@ -2,13 +2,24 @@
from django.core.management import BaseCommand
from django.db.models import Q
-from etools.applications.action_points.conditions import ActionPointAuthorCondition, ActionPointAssignedByCondition, \
- ActionPointAssigneeCondition
+from etools.applications.action_points.conditions import (
+ ActionPointAssignedByCondition,
+ ActionPointAssigneeCondition,
+ ActionPointAuthorCondition,
+)
from etools.applications.action_points.models import ActionPoint
-from etools.applications.audit.conditions import (AuditModuleCondition, AuditStaffMemberCondition,
- EngagementStaffMemberCondition,)
-from etools.applications.audit.models import Auditor, Engagement, UNICEFAuditFocalPoint, UNICEFUser, \
- EngagementActionPoint
+from etools.applications.audit.conditions import (
+ AuditModuleCondition,
+ AuditStaffMemberCondition,
+ EngagementStaffMemberCondition,
+)
+from etools.applications.audit.models import (
+ Auditor,
+ Engagement,
+ EngagementActionPoint,
+ UNICEFAuditFocalPoint,
+ UNICEFUser,
+)
from etools.applications.permissions2.conditions import GroupCondition, NewObjectCondition, ObjectStatusCondition
from etools.applications.permissions2.models import Permission
from etools.applications.permissions2.utils import get_model_target
diff --git a/src/etools/applications/audit/migrations/0009_auto_20180521_1052.py b/src/etools/applications/audit/migrations/0009_auto_20180521_1052.py
index 69808970b5..e7f6811808 100644
--- a/src/etools/applications/audit/migrations/0009_auto_20180521_1052.py
+++ b/src/etools/applications/audit/migrations/0009_auto_20180521_1052.py
@@ -3,7 +3,6 @@
from django.db import migrations
-
# engagement action point, action point
statuses_mapping = {
'open': 'open',
diff --git a/src/etools/applications/audit/migrations/0015_auto_20190312_2010.py b/src/etools/applications/audit/migrations/0015_auto_20190312_2010.py
index 5b77415e7a..70322ce21b 100644
--- a/src/etools/applications/audit/migrations/0015_auto_20190312_2010.py
+++ b/src/etools/applications/audit/migrations/0015_auto_20190312_2010.py
@@ -1,7 +1,7 @@
# Generated by Django 2.1.7 on 2019-03-12 20:10
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/src/etools/applications/audit/migrations/0016_auto_20190328_1528.py b/src/etools/applications/audit/migrations/0016_auto_20190328_1528.py
index 2acadd4702..e191fc29d7 100644
--- a/src/etools/applications/audit/migrations/0016_auto_20190328_1528.py
+++ b/src/etools/applications/audit/migrations/0016_auto_20190328_1528.py
@@ -1,6 +1,7 @@
# Generated by Django 2.1.7 on 2019-03-28 15:28
from django.db import migrations
+
import django_fsm
diff --git a/src/etools/applications/audit/purchase_order/admin.py b/src/etools/applications/audit/purchase_order/admin.py
index 593bb96b09..79469be1a4 100644
--- a/src/etools/applications/audit/purchase_order/admin.py
+++ b/src/etools/applications/audit/purchase_order/admin.py
@@ -1,7 +1,11 @@
from django.contrib import admin
-from etools.applications.audit.purchase_order.models import (AuditorFirm, AuditorStaffMember,
- PurchaseOrder, PurchaseOrderItem,)
+from etools.applications.audit.purchase_order.models import (
+ AuditorFirm,
+ AuditorStaffMember,
+ PurchaseOrder,
+ PurchaseOrderItem,
+)
class AuditorStaffMemberInlineAdmin(admin.StackedInline):
diff --git a/src/etools/applications/audit/purchase_order/migrations/0002_fix_null_values.py b/src/etools/applications/audit/purchase_order/migrations/0002_fix_null_values.py
index 71bb8422eb..41fc75608e 100644
--- a/src/etools/applications/audit/purchase_order/migrations/0002_fix_null_values.py
+++ b/src/etools/applications/audit/purchase_order/migrations/0002_fix_null_values.py
@@ -1,6 +1,7 @@
from django.db import migrations
+
class Migration(migrations.Migration):
dependencies = [
diff --git a/src/etools/applications/audit/purchase_order/tests/test_tasks.py b/src/etools/applications/audit/purchase_order/tests/test_tasks.py
index fa873e5135..5596f6cdce 100644
--- a/src/etools/applications/audit/purchase_order/tests/test_tasks.py
+++ b/src/etools/applications/audit/purchase_order/tests/test_tasks.py
@@ -1,7 +1,7 @@
from unittest.mock import patch
-from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.audit.purchase_order.tasks import update_purchase_orders
+from etools.applications.core.tests.cases import BaseTenantTestCase
class TestUpdatePurchaseOrders(BaseTenantTestCase):
diff --git a/src/etools/applications/audit/serializers/export.py b/src/etools/applications/audit/serializers/export.py
index 81003d9401..0de02aacf9 100644
--- a/src/etools/applications/audit/serializers/export.py
+++ b/src/etools/applications/audit/serializers/export.py
@@ -20,10 +20,7 @@
)
from etools.applications.audit.purchase_order.models import AuditorFirm, AuditorStaffMember, PurchaseOrder
from etools.applications.audit.serializers.auditor import PurchaseOrderItemSerializer
-from etools.applications.audit.serializers.engagement import (
- DetailedFindingInfoSerializer,
- KeyInternalControlSerializer,
-)
+from etools.applications.audit.serializers.engagement import DetailedFindingInfoSerializer, KeyInternalControlSerializer
from etools.applications.audit.serializers.risks import (
AggregatedRiskRootSerializer,
KeyInternalWeaknessSerializer,
diff --git a/src/etools/applications/audit/tests/base.py b/src/etools/applications/audit/tests/base.py
index 9904840514..a32c7ccbb6 100644
--- a/src/etools/applications/audit/tests/base.py
+++ b/src/etools/applications/audit/tests/base.py
@@ -14,11 +14,13 @@
from etools.applications.audit.models import RiskBluePrint
from etools.applications.audit.tests.factories import (
+ AuditFocalPointUserFactory,
AuditorStaffMemberFactory,
+ AuditorUserFactory,
AuditPartnerFactory,
RiskFactory,
- AuditorUserFactory, AuditFocalPointUserFactory)
-from etools.applications.users.tests.factories import UserFactory, SimpleUserFactory
+)
+from etools.applications.users.tests.factories import SimpleUserFactory, UserFactory
from etools.libraries.djangolib.models import GroupWrapper
diff --git a/src/etools/applications/audit/tests/factories.py b/src/etools/applications/audit/tests/factories.py
index da1b4016aa..5286ae80e9 100644
--- a/src/etools/applications/audit/tests/factories.py
+++ b/src/etools/applications/audit/tests/factories.py
@@ -6,12 +6,29 @@
import factory
from factory import fuzzy
-from etools.applications.audit.models import (Audit, Auditor, DetailedFindingInfo, Engagement,
- Finding, KeyInternalControl, MicroAssessment,
- Risk, RiskBluePrint, RiskCategory, SpecialAudit, SpecificProcedure,
- SpotCheck, UNICEFAuditFocalPoint, UNICEFUser,)
-from etools.applications.audit.purchase_order.models import (AuditorFirm, AuditorStaffMember,
- PurchaseOrder, PurchaseOrderItem,)
+from etools.applications.audit.models import (
+ Audit,
+ Auditor,
+ DetailedFindingInfo,
+ Engagement,
+ Finding,
+ KeyInternalControl,
+ MicroAssessment,
+ Risk,
+ RiskBluePrint,
+ RiskCategory,
+ SpecialAudit,
+ SpecificProcedure,
+ SpotCheck,
+ UNICEFAuditFocalPoint,
+ UNICEFUser,
+)
+from etools.applications.audit.purchase_order.models import (
+ AuditorFirm,
+ AuditorStaffMember,
+ PurchaseOrder,
+ PurchaseOrderItem,
+)
from etools.applications.firms.tests.factories import BaseFirmFactory, BaseStaffMemberFactory
from etools.applications.partners.models import PartnerOrganization
from etools.applications.partners.tests.factories import AgreementFactory, InterventionFactory, PartnerFactory
diff --git a/src/etools/applications/audit/tests/test_email.py b/src/etools/applications/audit/tests/test_email.py
index de1bd94e8e..7aa15ac95b 100644
--- a/src/etools/applications/audit/tests/test_email.py
+++ b/src/etools/applications/audit/tests/test_email.py
@@ -4,9 +4,9 @@
from unicef_notification.models import EmailTemplate
-from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.audit.tests.factories import AuditFocalPointUserFactory
from etools.applications.audit.tests.test_transitions import MATransitionsTestCaseMixin
+from etools.applications.core.tests.cases import BaseTenantTestCase
class TestEmail(BaseTenantTestCase):
diff --git a/src/etools/applications/audit/tests/test_models.py b/src/etools/applications/audit/tests/test_models.py
index 281064c8dc..bdf664af5e 100644
--- a/src/etools/applications/audit/tests/test_models.py
+++ b/src/etools/applications/audit/tests/test_models.py
@@ -9,15 +9,24 @@
from django.db import connection
from django.test import SimpleTestCase
-
from etools.applications.audit.models import Auditor, Engagement, RiskCategory
from etools.applications.audit.purchase_order.models import AuditorStaffMember, PurchaseOrder, PurchaseOrderItem
-from etools.applications.audit.tests.factories import (AuditFactory, AuditorStaffMemberFactory, AuditPartnerFactory,
- DetailedFindingInfoFactory,
- EngagementFactory, FindingFactory, MicroAssessmentFactory,
- PurchaseOrderFactory, PurchaseOrderItemFactory,
- RiskBluePrintFactory, RiskCategoryFactory, RiskFactory,
- SpecialAuditFactory, SpotCheckFactory,)
+from etools.applications.audit.tests.factories import (
+ AuditFactory,
+ AuditorStaffMemberFactory,
+ AuditPartnerFactory,
+ DetailedFindingInfoFactory,
+ EngagementFactory,
+ FindingFactory,
+ MicroAssessmentFactory,
+ PurchaseOrderFactory,
+ PurchaseOrderItemFactory,
+ RiskBluePrintFactory,
+ RiskCategoryFactory,
+ RiskFactory,
+ SpecialAuditFactory,
+ SpotCheckFactory,
+)
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.firms.tests.factories import BaseUserFactory
from etools.applications.users.models import Country
diff --git a/src/etools/applications/audit/tests/test_views.py b/src/etools/applications/audit/tests/test_views.py
index 8f41608057..d53b0329bf 100644
--- a/src/etools/applications/audit/tests/test_views.py
+++ b/src/etools/applications/audit/tests/test_views.py
@@ -15,6 +15,7 @@
from etools.applications.audit.tests.base import AuditTestCaseMixin, EngagementTransitionsTestCaseMixin
from etools.applications.audit.tests.factories import (
AuditFactory,
+ AuditorUserFactory,
AuditPartnerFactory,
EngagementFactory,
MicroAssessmentFactory,
@@ -25,7 +26,7 @@
SpotCheckFactory,
StaffSpotCheckFactory,
UserFactory,
- AuditorUserFactory)
+)
from etools.applications.audit.tests.test_transitions import MATransitionsTestCaseMixin
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import PartnerType
diff --git a/src/etools/applications/tpm/filters.py b/src/etools/applications/tpm/filters.py
index 713b36fff9..2a09dade09 100644
--- a/src/etools/applications/tpm/filters.py
+++ b/src/etools/applications/tpm/filters.py
@@ -26,6 +26,7 @@ class Meta:
'tpm_activities__section': ['exact', 'in'],
'tpm_activities__partner': ['exact', 'in'],
'tpm_activities__locations': ['exact'],
+ 'tpm_activities__offices': ['exact'],
'tpm_activities__cp_output': ['exact', 'in'],
'tpm_activities__intervention': ['exact'],
'tpm_activities__date': ['exact', 'lte', 'gte', 'gt', 'lt'],
From 437ae9b82a34eca6a051206b854addd2d3418964 Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Thu, 18 Apr 2019 08:18:21 -0400
Subject: [PATCH 48/79] Add xlsx export got action points
---
.../applications/action_points/serializers.py | 83 +++++++++++++++++++
.../action_points/tests/test_views.py | 41 +++++++++
.../applications/action_points/views.py | 46 +++++++---
3 files changed, 159 insertions(+), 11 deletions(-)
diff --git a/src/etools/applications/action_points/serializers.py b/src/etools/applications/action_points/serializers.py
index 41ba3a12f3..a345242ccf 100644
--- a/src/etools/applications/action_points/serializers.py
+++ b/src/etools/applications/action_points/serializers.py
@@ -4,6 +4,7 @@
from django_comments.models import Comment
from rest_framework import serializers
from unicef_locations.serializers import LocationLightSerializer
+from unicef_rest_export.serializers import ExportSerializer
from unicef_restlib.fields import SeparatedReadWriteField
from unicef_restlib.serializers import UserContextSerializerMixin, WritableNestedSerializerMixin
from unicef_snapshot.models import Activity
@@ -180,3 +181,85 @@ def validate_category(self, value):
if value and value.module != self.instance.related_module:
raise serializers.ValidationError(_('Category doesn\'t belong to selected module.'))
return value
+
+
+class ActionPointListExportSerializer(ExportSerializer):
+ engagement = serializers.SerializerMethodField()
+ tpm_activity = serializers.SerializerMethodField()
+ travel_activity = serializers.SerializerMethodField()
+
+ class Meta(ActionPointListSerializer.Meta):
+ pass
+
+ def get_engagement(self, obj):
+ return obj.engagement
+
+ def get_tpm_activity(self, obj):
+ return obj.tpm_activity
+
+ def get_travel_activity(self, obj):
+ return obj.travel_activity
+
+ def get_headers(self, data):
+ headers = []
+ for field in data[0].keys():
+ headers.append(str(self.get_header_label(field)))
+ return headers
+
+ def transform_cp_output(self, data):
+ return ",".join(["231" for x in data])
+
+ def transform_location(self, data):
+ return data.get("name", "")
+
+ def transform_office(self, data):
+ return data.get("name", "")
+
+ def transform_section(self, data):
+ return data.get("name", "")
+
+ def transform_author(self, data):
+ return "{} {}".format(
+ data.get("first_name", ""),
+ data.get("last_name", "")
+ )
+
+ def transform_assigned_by(self, data):
+ return "{} {}".format(
+ data.get("first_name", ""),
+ data.get("last_name", "")
+ )
+
+ def transform_assigned_to(self, data):
+ return "{} {}".format(
+ data.get("first_name", ""),
+ data.get("last_name", "")
+ )
+
+ def transform_partner(self, data):
+ return data.get("name", "")
+
+ def transform_intervention(self, data):
+ return data.get("number", "")
+
+ def transform_category(self, data):
+ return data.get("module", "")
+
+ def transform_dataset(self, dataset):
+ transform_fields = [
+ 'category',
+ 'assigned_to',
+ 'author',
+ 'assigned_by',
+ 'section',
+ 'office',
+ 'cp_output',
+ 'partner',
+ 'intervention',
+ 'location',
+ ]
+ from tablib.compat import unicode
+ for field in transform_fields:
+ func = getattr(self, "transform_{}".format(field))
+ dataset.add_formatter(str(self.get_header_label(field)), func)
+ return dataset
diff --git a/src/etools/applications/action_points/tests/test_views.py b/src/etools/applications/action_points/tests/test_views.py
index b12cdeeec7..56af03362a 100644
--- a/src/etools/applications/action_points/tests/test_views.py
+++ b/src/etools/applications/action_points/tests/test_views.py
@@ -277,11 +277,52 @@ def test_list_csv(self):
self._test_export(self.pme_user, 'action-points:action-points-list-csv-export')
+ def test_list_xlsx(self):
+ ActionPointFactory(status='open', comments__count=1)
+ ActionPointFactory(
+ status='open',
+ comments__count=1,
+ engagement=MicroAssessmentFactory(),
+ )
+ ActionPointFactory(
+ status='open',
+ comments__count=1,
+ tpm_activity=TPMVisitFactory(
+ tpm_activities__count=1
+ ).tpm_activities.first(),
+ )
+ traveler = UserFactory()
+ ActionPointFactory(
+ status='open',
+ travel_activity=TravelActivityFactory(
+ primary_traveler=traveler,
+ travels=[TravelFactory(traveler=traveler)]
+ )
+ )
+
+ self._test_export(
+ self.pme_user,
+ 'action-points:action-points-list-xlsx-export',
+ )
+
def test_single_csv(self):
action_point = ActionPointFactory(status='open', comments__count=1, engagement=MicroAssessmentFactory())
self._test_export(self.pme_user, 'action-points:action-points-single-csv-export', args=[action_point.id])
+ def test_single_xlsx(self):
+ action_point = ActionPointFactory(
+ status='open',
+ comments__count=1,
+ engagement=MicroAssessmentFactory(),
+ )
+
+ self._test_export(
+ self.pme_user,
+ 'action-points:action-points-single-xlsx-export',
+ args=[action_point.id],
+ )
+
class TestActionPointsViewMetadata(ActionPointsTestCaseMixin):
@classmethod
diff --git a/src/etools/applications/action_points/views.py b/src/etools/applications/action_points/views.py
index b053a34b77..b1a0f06d71 100644
--- a/src/etools/applications/action_points/views.py
+++ b/src/etools/applications/action_points/views.py
@@ -6,6 +6,8 @@
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
+from unicef_rest_export.renderers import ExportExcelRenderer
+from unicef_rest_export.views import ExportMixin
from unicef_restlib.pagination import DynamicPageNumberPagination
from unicef_restlib.views import MultiSerializerViewSetMixin, SafeTenantViewSetMixin
from unicef_snapshot.views import FSMSnapshotViewMixin
@@ -26,6 +28,7 @@
from etools.applications.action_points.models import ActionPoint
from etools.applications.action_points.serializers import (
ActionPointCreateSerializer,
+ ActionPointListExportSerializer,
ActionPointListSerializer,
ActionPointSerializer,
)
@@ -42,17 +45,18 @@ class CategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
class ActionPointViewSet(
- SafeTenantViewSetMixin,
- MultiSerializerViewSetMixin,
- PermittedSerializerMixin,
- mixins.ListModelMixin,
- mixins.CreateModelMixin,
- mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- mixins.DestroyModelMixin,
- FSMSnapshotViewMixin,
- PermittedFSMActionMixin,
- viewsets.GenericViewSet
+ SafeTenantViewSetMixin,
+ MultiSerializerViewSetMixin,
+ PermittedSerializerMixin,
+ ExportMixin,
+ mixins.ListModelMixin,
+ mixins.CreateModelMixin,
+ mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.DestroyModelMixin,
+ FSMSnapshotViewMixin,
+ PermittedFSMActionMixin,
+ viewsets.GenericViewSet
):
metadata_class = PermissionBasedMetadata
pagination_class = DynamicPageNumberPagination
@@ -63,6 +67,7 @@ class ActionPointViewSet(
'create': ActionPointCreateSerializer,
'list': ActionPointListSerializer,
}
+ export_serializer_class = ActionPointListExportSerializer
filter_backends = (ReferenceNumberOrderingFilter, OrderingFilter, SearchFilter,
RelatedModuleFilter, DjangoFilterBackend,)
@@ -112,6 +117,15 @@ def list_csv_export(self, request, *args, **kwargs):
'Content-Disposition': 'attachment;filename=action_points_{}.csv'.format(timezone.now().date())
})
+ @action(detail=False, methods=['get'], url_path='export/xlsx', renderer_classes=(ExportExcelRenderer,))
+ def list_xlsx_export(self, request, *args, **kwargs):
+ self.serializer_class = ActionPointListSerializer
+ action_points = self.filter_queryset(self.get_queryset().prefetch_related('comments'))
+ serializer = self.get_serializer(action_points, many=True)
+ return Response(serializer.data, headers={
+ 'Content-Disposition': 'attachment;filename=action_points_{}.xlsx'.format(timezone.now().date())
+ })
+
@action(detail=True, methods=['get'], url_path='export/csv', renderer_classes=(ActionPointCSVRenderer,))
def single_csv_export(self, request, *args, **kwargs):
serializer = ActionPointExportSerializer(self.get_object())
@@ -120,3 +134,13 @@ def single_csv_export(self, request, *args, **kwargs):
self.get_object().reference_number, timezone.now().date()
)
})
+
+ @action(detail=True, methods=['get'], url_path='export/xlsx', renderer_classes=(ExportExcelRenderer,))
+ def single_xlsx_export(self, request, *args, **kwargs):
+ self.serializer_class = ActionPointListSerializer
+ serializer = self.get_serializer([self.get_object()], many=True)
+ return Response(serializer.data, headers={
+ 'Content-Disposition': 'attachment;filename={}_{}.xlsx'.format(
+ self.get_object().reference_number, timezone.now().date()
+ )
+ })
From 9653c2ec53285f97464a64a4109b958dbdbe492e Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Thu, 18 Apr 2019 08:20:05 -0400
Subject: [PATCH 49/79] flake8 cleanup
---
src/etools/applications/action_points/serializers.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/etools/applications/action_points/serializers.py b/src/etools/applications/action_points/serializers.py
index a345242ccf..1341fd9d3c 100644
--- a/src/etools/applications/action_points/serializers.py
+++ b/src/etools/applications/action_points/serializers.py
@@ -258,7 +258,6 @@ def transform_dataset(self, dataset):
'intervention',
'location',
]
- from tablib.compat import unicode
for field in transform_fields:
func = getattr(self, "transform_{}".format(field))
dataset.add_formatter(str(self.get_header_label(field)), func)
From 914fd53d61dad37b4abbb7ed9a72bf0dd9759ccc Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Thu, 18 Apr 2019 08:57:07 -0400
Subject: [PATCH 50/79] Make action points xslx export more robust
---
.../applications/action_points/serializers.py | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/etools/applications/action_points/serializers.py b/src/etools/applications/action_points/serializers.py
index 1341fd9d3c..cc3f6affad 100644
--- a/src/etools/applications/action_points/serializers.py
+++ b/src/etools/applications/action_points/serializers.py
@@ -207,15 +207,23 @@ def get_headers(self, data):
return headers
def transform_cp_output(self, data):
- return ",".join(["231" for x in data])
+ if data is None:
+ return data
+ return data.get("result_name", "")
def transform_location(self, data):
+ if data is None:
+ return data
return data.get("name", "")
def transform_office(self, data):
+ if data is None:
+ return data
return data.get("name", "")
def transform_section(self, data):
+ if data is None:
+ return data
return data.get("name", "")
def transform_author(self, data):
@@ -237,12 +245,18 @@ def transform_assigned_to(self, data):
)
def transform_partner(self, data):
+ if data is None:
+ return data
return data.get("name", "")
def transform_intervention(self, data):
+ if data is None:
+ return data
return data.get("number", "")
def transform_category(self, data):
+ if data is None:
+ return data
return data.get("module", "")
def transform_dataset(self, dataset):
From 2ee5e792f88881e7ea4a6b0d81b914b8628e2b08 Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Fri, 29 Mar 2019 08:01:45 -0400
Subject: [PATCH 51/79] Update attachment file type static results
---
src/etools/applications/attachments/models.py | 7 +++++++
src/etools/applications/partners/views/v2.py | 7 ++-----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/etools/applications/attachments/models.py b/src/etools/applications/attachments/models.py
index 69c0c0efd8..5d429f5a25 100644
--- a/src/etools/applications/attachments/models.py
+++ b/src/etools/applications/attachments/models.py
@@ -284,3 +284,10 @@ class AttachmentFlat(models.Model):
def __str__(self):
return str(self.attachment)
+
+ @classmethod
+ def get_file_types(cls):
+ return cls.objects.exclude(file_type="").values_list(
+ "file_type",
+ flat=True
+ ).distinct("file_type").order_by("file_type")
diff --git a/src/etools/applications/partners/views/v2.py b/src/etools/applications/partners/views/v2.py
index 8f11801c77..5536c2eda4 100644
--- a/src/etools/applications/partners/views/v2.py
+++ b/src/etools/applications/partners/views/v2.py
@@ -11,10 +11,10 @@
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.response import Response
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 etools.applications.attachments.models import AttachmentFlat
from etools.applications.funds.models import FundsReservationItem
from etools.applications.partners.filters import PartnerScopeFilter
from etools.applications.partners.models import (
@@ -97,10 +97,7 @@ def get(self, request):
# hardcoded to partners app attachments for now
# once tpm and audit come online we can remove the filter
# on attachment file types
- attachment_types = AttachmentFileType.objects.values_list(
- 'label',
- flat=True
- )
+ attachment_types = AttachmentFlat.get_file_types()
partner_file_types = FileType.objects.values_list("name", flat=True)
local_currency = local_workspace.local_currency.id if local_workspace.local_currency else None
From 6148ad30f95d59b758f864b568890e6ab9ea21a3 Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Thu, 11 Apr 2019 04:09:51 -0400
Subject: [PATCH 52/79] Add attachment_types_active to dropdown static endpoint
---
src/etools/applications/partners/views/v2.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/etools/applications/partners/views/v2.py b/src/etools/applications/partners/views/v2.py
index 5536c2eda4..abd8c8a9eb 100644
--- a/src/etools/applications/partners/views/v2.py
+++ b/src/etools/applications/partners/views/v2.py
@@ -94,10 +94,11 @@ def get(self, request):
intervention_amendment_types = choices_to_json_ready(InterventionAmendment.AMENDMENT_TYPES)
location_types = GatewayType.objects.values('id', 'name', 'admin_level').order_by('id')
currencies = choices_to_json_ready(CURRENCIES)
- # hardcoded to partners app attachments for now
- # once tpm and audit come online we can remove the filter
- # on attachment file types
- attachment_types = AttachmentFlat.get_file_types()
+ attachment_types = AttachmentFileType.objects.values_list(
+ "label",
+ flat=True,
+ )
+ attachment_types_active = AttachmentFlat.get_file_types()
partner_file_types = FileType.objects.values_list("name", flat=True)
local_currency = local_workspace.local_currency.id if local_workspace.local_currency else None
From 36b7cb0201a9d9618298ca209133f6d2f0833d8d Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Thu, 11 Apr 2019 04:17:51 -0400
Subject: [PATCH 53/79] Fix missing import and setting of
attachment_types_active data
---
src/etools/applications/partners/views/v2.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/etools/applications/partners/views/v2.py b/src/etools/applications/partners/views/v2.py
index abd8c8a9eb..84d5378938 100644
--- a/src/etools/applications/partners/views/v2.py
+++ b/src/etools/applications/partners/views/v2.py
@@ -11,6 +11,7 @@
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.response import Response
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
@@ -120,6 +121,7 @@ def get(self, request):
'local_currency': local_currency,
'location_types': location_types,
'attachment_types': attachment_types,
+ 'attachment_types_active': attachment_types_active,
'partner_file_types': partner_file_types,
},
status=status.HTTP_200_OK
From a2779b8a0d5c405d240cfc22426c615674606f0a Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Thu, 11 Apr 2019 05:10:35 -0400
Subject: [PATCH 54/79] Fix tests for attachment_types_active
---
src/etools/applications/partners/tests/test_api_pmp.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/etools/applications/partners/tests/test_api_pmp.py b/src/etools/applications/partners/tests/test_api_pmp.py
index f3545b99a8..95782af5a0 100644
--- a/src/etools/applications/partners/tests/test_api_pmp.py
+++ b/src/etools/applications/partners/tests/test_api_pmp.py
@@ -64,6 +64,7 @@ def setUp(self):
'local_currency',
'location_types',
'attachment_types',
+ 'attachment_types_active',
'partner_file_types',
'partner_risk_rating',
))
From eb0017566e9d6ae1cde5966d3b5d6acaf3d1cdc1 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Thu, 18 Apr 2019 12:02:30 -0400
Subject: [PATCH 55/79] updated pipfile
---
Pipfile.lock | 142 +++++++++++++++++++++++++++------------------------
1 file changed, 75 insertions(+), 67 deletions(-)
diff --git a/Pipfile.lock b/Pipfile.lock
index 21410ba3e4..da61d2af2c 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "beb7919c535f514b0bcac8c651a52fdca8cfcfb5d0262a974b956d1711b7fe24"
+ "sha256": "ddd8d7caf5411f5c981f09778a0a8309645ba49166bd747b93df2ffa73667b61"
},
"pipfile-spec": 6,
"requires": {
@@ -176,11 +176,11 @@
},
"defusedxml": {
"hashes": [
- "sha256:24d7f2f94f7f3cb6061acb215685e5125fbcdc40a857eff9de22518820b0a4f4",
- "sha256:702a91ade2968a82beb0db1e0766a6a273f33d4616a6ce8cde475d8e09853b20"
+ "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93",
+ "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"
],
"markers": "python_version >= '3.0'",
- "version": "==0.5.0"
+ "version": "==0.6.0"
},
"diff-match-patch": {
"hashes": [
@@ -259,20 +259,20 @@
"index": "pypi",
"version": "==2.5"
},
- "django-debug-toolbar": {
+ "django-easy-pdf": {
"hashes": [
- "sha256:89d75b60c65db363fb24688d977e5fbf0e73386c67acf562d278402a10fc3736",
- "sha256:c2b0134119a624f4ac9398b44f8e28a01c7686ac350a12a74793f3dd57a9eea0"
+ "sha256:f7cb58e896791d28718219c54d2c8930e442fa1327817037e1c480bead77cddb"
],
"index": "pypi",
- "version": "==1.11"
+ "version": "==0.1.1"
},
- "django-easy-pdf": {
+ "django-extensions": {
"hashes": [
- "sha256:f7cb58e896791d28718219c54d2c8930e442fa1327817037e1c480bead77cddb"
+ "sha256:109004f80b6f45ad1f56addaa59debca91d94aa0dc1cb19678b9364b4fe9b6f4",
+ "sha256:307766e5e6c1caffe76c5d99239d8115d14ae3f7cab2cd991fcffd763dad904b"
],
"index": "pypi",
- "version": "==0.1.1"
+ "version": "==2.1.6"
},
"django-filter": {
"hashes": [
@@ -808,36 +808,36 @@
},
"reportlab": {
"hashes": [
- "sha256:063a4b9b269883e1ad69f17319a13bce29eb64b4ea83be0ca72f3c7e16eb82c5",
- "sha256:083d545873ee1d42f2489ad7a28de68ac1cd8b347f2909b58bf52e0b47c1db78",
- "sha256:11f7a4f42078ed7a1555ee4ec4ce9f1ee0c693c81cbec141ed9472efeac39d72",
- "sha256:2815d86bfcf113b357cae00886d94ceb84503d076d4840acdf20eb7bb18239e5",
- "sha256:28d2df4e6c82eda1decc9fd5ac8a92f11e3b589466aa0dfb5eecf2a6b37cc8b1",
- "sha256:348d8940ebcb3d387553a7d671621c5e191ddba54f52003d8f4762d599b8d1f1",
- "sha256:35a9ef0f962fa6cf0220bcb1784e803920ca133d1ca085f34bdf61c36a537ea0",
- "sha256:37c0678254aca7f9e18b8b3c60d6da19349b3149927026ce9578752b2bf831ac",
- "sha256:52c0e367ee6273499f1aa29a830e2a3abceae44446398f935774cfbce0fe0b6b",
- "sha256:534827c3dd5844340eb4ec61a754471a0fef3fd2e1f342ad9452b034529ce340",
- "sha256:577281844053e312cb90b29ea440ec6543416b3361833773a7eaadc361a25376",
- "sha256:58e4af53c64ec3b9c226d6c4e0bac5ec89a556fefc58eb058c9a5429385e4c84",
- "sha256:61c89741b03b6e5f434b41d8659d1a7df38b635bf09269abae1b00ee5cc77e24",
- "sha256:78f2ac8dc47c0cfbc3824aa3fc83ab8aa1e1f3a11803123f7a08170374c68b17",
- "sha256:7c66fbd111fb83b760a88d1b1bef9afb77d4c940c79e1c1e119f202be75e2d99",
- "sha256:8659c9fd61a042b47714dc3f637dfb3bff59396890386ae7a1c383ae3b76b206",
- "sha256:92113dcb7d98aa838782510a4f5654c7f6596e3560a0a4cf8f3eff141126e95a",
- "sha256:99d74fffc201a3bd4b603cc27901917c283e6deed1c8bf7c65d14ac1fb78f5e3",
- "sha256:9b9bdb2a9f7e35e8ad98fb06e7609616b7cfcdd510f55dcaf0335092ecdcb2ac",
- "sha256:9e6fc073ff383ef09ca67f0cc7028dfe96bd022d6117ff7d2586ea8ca7cd7a30",
- "sha256:a06e5c6873b420fe644cc813c660a64fbf4237be62b01576f32a305226bccfef",
- "sha256:a51c683366d4d46ae713d1395c5bc4d53f20943aa77e3590f7bbc3b374a3ff91",
- "sha256:a9b8f13783a83c82b33c3d7d175ff5b06c8b61e59bc0cd63965bc12d5328fbb8",
- "sha256:cdc4de4cd6041eda1624247949c689a17459394004572ff1fe14aa4ba7ad0b6a",
- "sha256:cf046304bea0e8b4574f3d500e15b119149d469dd3b17fec1b8005bdb0d6b8e6",
- "sha256:dc0cab2145fef216d3cf0577eca8780928fad7f021123eaa9ca2287f436754cc",
- "sha256:fad3a0fe7e616b064ddf5ad9f248eeb25e17f65cde204869f8d9a8c45ef17027",
- "sha256:fe276cd644e1e669613dc73fe6f7501c26e671d009d2329f774df578adc8000e"
- ],
- "version": "==3.5.18"
+ "sha256:1c228a3ac2c405f7fc16eac43ba92aec448bc25438902f30590ad021e8828097",
+ "sha256:2210fafd3bb06308a84876fe6d19172b645373edce2b6d7501378cb9c768f825",
+ "sha256:232fb2037b7c3df259685f1c5ecb7826f55742dc81f0713837b84a152307483e",
+ "sha256:2c4f25e63fa75f3064871cf435696a4e19b7bd4901d922b766ae58a447b5b6da",
+ "sha256:47951166d897b60e9e7ca349db82a2b689e6478ac6078e2c7c88ca8becbb0c7d",
+ "sha256:526ab1193ea8e97c4838135917890e66de5f777d04283008007229b139f3c094",
+ "sha256:5a9cc8470623ec5b76c7e59f56b7d1fcf0254896cd61842dbdbd278934cc50f4",
+ "sha256:5ddc1a4a74f225e35a7f60e2eae10de6878dddc9960dad2d9cadc49092f8850d",
+ "sha256:6b594f6d7d71bc5778e19adb1c699a598c69b9a7bcf97fa638d8762279f9d80a",
+ "sha256:6e8c89b46cfaf9ae40b7db87e9f29c9e5d32d18d25f9cd10d423a5241e8ec453",
+ "sha256:71f4f3e3975b91ddbfc1b36a537b46d07533ca7f31945e990a75db5f9bd7a0ba",
+ "sha256:763654dc346eeb66fa726a88d27f911339950d20a25303dfc098f3b59ba26614",
+ "sha256:7bae4b33363f44343e0fac5004c8e44576c3ed00885be4eee1f2260802c116c3",
+ "sha256:8a4b8a0fd0547f3b436b548284aa604ba183bfac26f41a7ffb23d0ff5db8c658",
+ "sha256:8b08d68e4cb498eabf85411beda5c32e591ef8d0a6d18c948c3f80ed5d2c6e31",
+ "sha256:9840f27948b54aefa3c6386e5ed0f124d641eb54fa2f2bc9aebcb270598487fc",
+ "sha256:9ae8f822370e47486ba1880f7580669058a41e64bdaa41019f4617317489f884",
+ "sha256:9db49197080646a113059eba1c0758161164de1bc57315e7422bbf8c86e03dcf",
+ "sha256:a08d23fa3f23f13a1cc6dca3b3c431d08ae48e52384e6bf47bbefb22fde58e61",
+ "sha256:ac111bc47733dbfa3e34d61282c91b69b1f66800b0c72b7b86dc2534faa09bef",
+ "sha256:bc3c69707c0bf9308193612d34ca87249d6fc91a35ce0873102321395d39024a",
+ "sha256:c375759a763c1c93d5b4f36620390440d9fa6dec6fcf88bce8234701d88b339c",
+ "sha256:c8a5988d73ec93a54f22660b64c5f3d2018163dd9ca4a5cdde8022a7e4fcb345",
+ "sha256:eba2bc7c28a3b2b0a3c24caff33e4d8708db008f480b03a6ea39c28661663746",
+ "sha256:ee187977d587b9b81929e08022f385eb11274efd75795d59d99eb23b3fa9b055",
+ "sha256:f3ef7616ffc27c150ffec61ac820739495f6a9ca5d8532047102756ebb27e8d1",
+ "sha256:f46f223fcae09c8bf2746b4eb2f351294faae04b262429cc480d34c69b133fd9",
+ "sha256:fd9f6429a68a246fb466696d97d1240752c889b5bfdc219fea15ae787cf366a6"
+ ],
+ "version": "==3.5.19"
},
"requests": {
"hashes": [
@@ -907,13 +907,6 @@
"index": "pypi",
"version": "==1.7.0"
},
- "sqlparse": {
- "hashes": [
- "sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177",
- "sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"
- ],
- "version": "==0.3.0"
- },
"static3": {
"hashes": [
"sha256:674641c64bc75507af2eb20bef7e7e3593dca993dec6674be108fa15b42f47c8"
@@ -1012,10 +1005,10 @@
},
"urllib3": {
"hashes": [
- "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
- "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"
+ "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
+ "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
],
- "version": "==1.24.1"
+ "version": "==1.24.2"
},
"vine": {
"hashes": [
@@ -1133,13 +1126,21 @@
],
"version": "==4.4.0"
},
- "django-extensions": {
+ "django": {
"hashes": [
- "sha256:109004f80b6f45ad1f56addaa59debca91d94aa0dc1cb19678b9364b4fe9b6f4",
- "sha256:307766e5e6c1caffe76c5d99239d8115d14ae3f7cab2cd991fcffd763dad904b"
+ "sha256:275bec66fd2588dd517ada59b8bfb23d4a9abc5a362349139ddda3c7ff6f5ade",
+ "sha256:939652e9d34d7d53d74d5d8ef82a19e5f8bb2de75618f7e5360691b6e9667963"
],
"index": "pypi",
- "version": "==2.1.6"
+ "version": "==2.1.7"
+ },
+ "django-debug-toolbar": {
+ "hashes": [
+ "sha256:89d75b60c65db363fb24688d977e5fbf0e73386c67acf562d278402a10fc3736",
+ "sha256:c2b0134119a624f4ac9398b44f8e28a01c7686ac350a12a74793f3dd57a9eea0"
+ ],
+ "index": "pypi",
+ "version": "==1.11"
},
"djangorestframework": {
"hashes": [
@@ -1181,10 +1182,10 @@
},
"faker": {
"hashes": [
- "sha256:00b7011757c4907546f17d0e47df098b542ea2b04c966ee0e80a493aae2c13c8",
- "sha256:745ac8b9c9526e338696e07b7f2e206e5e317e5744e22fdd7c2894bf19af41f1"
+ "sha256:167cef2454482dc2fbd8b0ff6a5ba3dbac8d3a3ebdee6ba819d008100d9d9428",
+ "sha256:3f2f4570df28df2eb8f39b00520eb610081d6552975e926c6a2cbc64fd89c4c1"
],
- "version": "==1.0.4"
+ "version": "==1.0.5"
},
"fancycompleter": {
"hashes": [
@@ -1482,10 +1483,10 @@
},
"sphinxcontrib-htmlhelp": {
"hashes": [
- "sha256:0d691ca8edf5995fbacfe69b191914256071a94cbad03c3688dca47385c9206c",
- "sha256:e31c8271f5a8f04b620a500c0442a7d5cfc1a732fa5c10ec363f90fe72af0cb8"
+ "sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422",
+ "sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7"
],
- "version": "==1.0.1"
+ "version": "==1.0.2"
},
"sphinxcontrib-jsmath": {
"hashes": [
@@ -1508,6 +1509,13 @@
],
"version": "==1.1.3"
},
+ "sqlparse": {
+ "hashes": [
+ "sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177",
+ "sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"
+ ],
+ "version": "==0.3.0"
+ },
"text-unidecode": {
"hashes": [
"sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d",
@@ -1524,11 +1532,11 @@
},
"tox": {
"hashes": [
- "sha256:69620e19de33a6b7ee8aeda5478791b3618ff58f0b869dbd0319fb71aa903deb",
- "sha256:e5cdb1653aa27b3e46b5c390de6b6d51d31afcfdbd9d1222d82d76b82ad03d9b"
+ "sha256:1b166b93d2ce66bb7b253ba944d2be89e0c9d432d49eeb9da2988b4902a4684e",
+ "sha256:665cbdd99f5c196dd80d1d8db8c8cf5d48b1ae1f778bccd1bdf14d5aaf4ca0fc"
],
"index": "pypi",
- "version": "==3.8.6"
+ "version": "==3.9.0"
},
"traitlets": {
"hashes": [
@@ -1539,10 +1547,10 @@
},
"urllib3": {
"hashes": [
- "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
- "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"
+ "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
+ "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
],
- "version": "==1.24.1"
+ "version": "==1.24.2"
},
"virtualenv": {
"hashes": [
From 1f10d75818d780de6529ce562872a40f04a6b112 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Thu, 18 Apr 2019 12:58:37 -0400
Subject: [PATCH 56/79] debug toolbar in requirements
---
Pipfile | 2 +-
Pipfile.lock | 40 ++++++++++++++++------------------------
2 files changed, 17 insertions(+), 25 deletions(-)
diff --git a/Pipfile b/Pipfile
index 92e306ef40..ce9d522f27 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,7 +4,6 @@ url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
-django-debug-toolbar = "==1.11"
flake8 = "*"
coverage = "*"
mock = "*"
@@ -31,6 +30,7 @@ django-celery-email = "==2.0.1"
django_celery_results = "==1.0.4"
django-contrib-comments = "==1.9.1"
django-cors-headers = "==2.5"
+django-debug-toolbar = "==1.11"
django-extensions = "==2.1.6"
django-easy-pdf = "==0.1.1"
django-filter = "==2.1"
diff --git a/Pipfile.lock b/Pipfile.lock
index da61d2af2c..16666c8608 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "ddd8d7caf5411f5c981f09778a0a8309645ba49166bd747b93df2ffa73667b61"
+ "sha256": "b1872df511fe7116c492e4f6b61490861452a922bd0e6b11049c49dd0c4d1906"
},
"pipfile-spec": 6,
"requires": {
@@ -259,6 +259,14 @@
"index": "pypi",
"version": "==2.5"
},
+ "django-debug-toolbar": {
+ "hashes": [
+ "sha256:89d75b60c65db363fb24688d977e5fbf0e73386c67acf562d278402a10fc3736",
+ "sha256:c2b0134119a624f4ac9398b44f8e28a01c7686ac350a12a74793f3dd57a9eea0"
+ ],
+ "index": "pypi",
+ "version": "==1.11"
+ },
"django-easy-pdf": {
"hashes": [
"sha256:f7cb58e896791d28718219c54d2c8930e442fa1327817037e1c480bead77cddb"
@@ -907,6 +915,13 @@
"index": "pypi",
"version": "==1.7.0"
},
+ "sqlparse": {
+ "hashes": [
+ "sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177",
+ "sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"
+ ],
+ "version": "==0.3.0"
+ },
"static3": {
"hashes": [
"sha256:674641c64bc75507af2eb20bef7e7e3593dca993dec6674be108fa15b42f47c8"
@@ -1126,22 +1141,6 @@
],
"version": "==4.4.0"
},
- "django": {
- "hashes": [
- "sha256:275bec66fd2588dd517ada59b8bfb23d4a9abc5a362349139ddda3c7ff6f5ade",
- "sha256:939652e9d34d7d53d74d5d8ef82a19e5f8bb2de75618f7e5360691b6e9667963"
- ],
- "index": "pypi",
- "version": "==2.1.7"
- },
- "django-debug-toolbar": {
- "hashes": [
- "sha256:89d75b60c65db363fb24688d977e5fbf0e73386c67acf562d278402a10fc3736",
- "sha256:c2b0134119a624f4ac9398b44f8e28a01c7686ac350a12a74793f3dd57a9eea0"
- ],
- "index": "pypi",
- "version": "==1.11"
- },
"djangorestframework": {
"hashes": [
"sha256:8a435df9007c8b7d8e69a21ef06650e3c0cbe0d4b09e55dd1bd74c89a75a9fcd",
@@ -1509,13 +1508,6 @@
],
"version": "==1.1.3"
},
- "sqlparse": {
- "hashes": [
- "sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177",
- "sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"
- ],
- "version": "==0.3.0"
- },
"text-unidecode": {
"hashes": [
"sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d",
From a3cbfa55c4bdc7cd854172cbbe44f283535382fe Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Thu, 18 Apr 2019 14:42:16 -0400
Subject: [PATCH 57/79] fix intervention many 2 many issue
---
.../migrations/0036_auto_20190418_1832.py | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 src/etools/applications/partners/migrations/0036_auto_20190418_1832.py
diff --git a/src/etools/applications/partners/migrations/0036_auto_20190418_1832.py b/src/etools/applications/partners/migrations/0036_auto_20190418_1832.py
new file mode 100644
index 0000000000..b9c7fac61f
--- /dev/null
+++ b/src/etools/applications/partners/migrations/0036_auto_20190418_1832.py
@@ -0,0 +1,33 @@
+# Generated by Django 2.1.7 on 2019-04-18 18:32
+
+from django.db import connection, migrations, ProgrammingError
+
+
+def rename_many_to_many_key(apps, schema_editor):
+
+ with connection.cursor() as cursor:
+ try:
+ cursor.execute('SELECT sector_id FROM partners_intervention_sections')
+ cursor.execute('ALTER TABLE "partners_intervention_sections" RENAME COLUMN "sector_id" TO "section_id";')
+ except ProgrammingError:
+ pass # first statement will fail since is already section_id
+
+
+def undo_many_to_many_key(apps, schema_editor):
+ with connection.cursor() as cursor:
+ try:
+ cursor.execute('SELECT section_id FROM partners_intervention_sections')
+ cursor.execute('ALTER TABLE "partners_intervention_sections" RENAME COLUMN "section_id" TO "sector_id";')
+ except ProgrammingError:
+ pass # first statement will fail since is already sector_id
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('partners', '0035_auto_20190404_0858'),
+ ]
+
+ operations = [
+ migrations.RunPython(rename_many_to_many_key, undo_many_to_many_key),
+ ]
From bb5ec16f0a177a164e89613340e53fdce350ffb8 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Thu, 18 Apr 2019 21:39:26 -0400
Subject: [PATCH 58/79] 10400 admin for engagements, isort
---
.isort.cfg | 1 +
src/etools/applications/attachments/models.py | 3 +--
.../attachments/tests/factories.py | 1 -
.../attachments/tests/test_commands.py | 1 +
.../attachments/tests/test_views.py | 11 ++---------
src/etools/applications/audit/admin.py | 2 +-
src/etools/applications/core/auth.py | 3 +--
src/etools/applications/core/middleware.py | 1 +
.../core/migrations/0001_initial.py | 2 +-
src/etools/applications/core/tests/cases.py | 6 +++---
.../applications/core/tests/test_middleware.py | 2 +-
.../environment/tests/test_views.py | 2 +-
.../applications/firms/tests/test_utils.py | 1 -
src/etools/applications/funds/admin.py | 10 ++++++++--
src/etools/applications/funds/serializers.py | 10 ++++++++--
.../applications/funds/tests/test_api.py | 14 +++++++++-----
.../applications/funds/tests/test_models.py | 11 ++++++++---
.../funds/tests/test_synchronizers.py | 18 +++++++++++++-----
.../applications/funds/tests/test_views.py | 6 +-----
src/etools/applications/funds/urls.py | 12 +++++++++---
.../management/commands/freeze_hact_data.py | 2 +-
src/etools/applications/hact/models.py | 2 +-
src/etools/applications/permissions2/models.py | 1 -
src/etools/applications/vision/tasks.py | 4 ++--
.../vision/tests/test_synchronizers.py | 7 +++++--
25 files changed, 79 insertions(+), 54 deletions(-)
diff --git a/.isort.cfg b/.isort.cfg
index 9a5035ac1d..4890e36deb 100644
--- a/.isort.cfg
+++ b/.isort.cfg
@@ -10,3 +10,4 @@ line_length = 119
balanced_wrapping = true
order_by_type = false
not_skip = __init__.py
+skip_glob = **/migrations/**
diff --git a/src/etools/applications/attachments/models.py b/src/etools/applications/attachments/models.py
index 5d429f5a25..134113b584 100644
--- a/src/etools/applications/attachments/models.py
+++ b/src/etools/applications/attachments/models.py
@@ -5,14 +5,13 @@
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
-from django.db import models, connection
+from django.db import connection, models
from django.urls import reverse
from django.utils.text import slugify
from django.utils.translation import ugettext as _
from model_utils.models import TimeStampedModel
from ordered_model.models import OrderedModel
-
from unicef_attachments.models import Attachment as NewAttachment
diff --git a/src/etools/applications/attachments/tests/factories.py b/src/etools/applications/attachments/tests/factories.py
index 32784fa4de..4c058d4902 100644
--- a/src/etools/applications/attachments/tests/factories.py
+++ b/src/etools/applications/attachments/tests/factories.py
@@ -1,6 +1,5 @@
import factory.django
from factory import fuzzy
-
from unicef_attachments.models import Attachment, AttachmentLink, FileType
diff --git a/src/etools/applications/attachments/tests/test_commands.py b/src/etools/applications/attachments/tests/test_commands.py
index 2113d6443f..e2849039f0 100644
--- a/src/etools/applications/attachments/tests/test_commands.py
+++ b/src/etools/applications/attachments/tests/test_commands.py
@@ -1,6 +1,7 @@
from django.core.management import call_command
from unicef_attachments.utils import get_attachment_flat_model
+
from etools.applications.attachments.tests.factories import AttachmentFactory, AttachmentFileTypeFactory
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/attachments/tests/test_views.py b/src/etools/applications/attachments/tests/test_views.py
index d49c4d827a..ff73dc6c28 100644
--- a/src/etools/applications/attachments/tests/test_views.py
+++ b/src/etools/applications/attachments/tests/test_views.py
@@ -2,10 +2,7 @@
from rest_framework import status
-from etools.applications.attachments.tests.factories import (
- AttachmentFactory,
- AttachmentFileTypeFactory,
-)
+from etools.applications.attachments.tests.factories import AttachmentFactory, AttachmentFileTypeFactory
from etools.applications.audit.tests.factories import EngagementFactory
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import PartnerType
@@ -19,11 +16,7 @@
InterventionResultLinkFactory,
PartnerFactory,
)
-from etools.applications.tpm.tests.factories import (
- SimpleTPMPartnerFactory,
- TPMActivityFactory,
- TPMVisitFactory,
-)
+from etools.applications.tpm.tests.factories import SimpleTPMPartnerFactory, TPMActivityFactory, TPMVisitFactory
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/audit/admin.py b/src/etools/applications/audit/admin.py
index a2a1b20973..9a7d969241 100644
--- a/src/etools/applications/audit/admin.py
+++ b/src/etools/applications/audit/admin.py
@@ -30,7 +30,7 @@ class EngagementAdmin(admin.ModelAdmin):
'status', 'start_date', 'end_date', 'status', 'engagement_type',
]
search_fields = 'partner__name', 'agreement__auditor_firm__name',
- filter_horizontal = ('authorized_officers', )
+ filter_horizontal = ('authorized_officers', 'active_pd', 'staff_members')
@admin.register(RiskCategory)
diff --git a/src/etools/applications/core/auth.py b/src/etools/applications/core/auth.py
index 982ca7b786..72dbae5651 100644
--- a/src/etools/applications/core/auth.py
+++ b/src/etools/applications/core/auth.py
@@ -10,9 +10,8 @@
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.utils import jwt_payload_handler
-from social_core.pipeline import social_auth
-from social_core.pipeline import user as social_core_user
from social_core.backends.azuread_b2c import AzureADB2COAuth2
+from social_core.pipeline import social_auth, user as social_core_user
from social_django.middleware import SocialAuthExceptionMiddleware
from etools.applications.users.models import Country
diff --git a/src/etools/applications/core/middleware.py b/src/etools/applications/core/middleware.py
index 63c63b0b43..f788fd8bc0 100644
--- a/src/etools/applications/core/middleware.py
+++ b/src/etools/applications/core/middleware.py
@@ -6,6 +6,7 @@
from django.http.response import HttpResponseRedirect
from django.template.response import SimpleTemplateResponse
from django.urls import reverse
+
from django_tenants.middleware import TenantMiddleware
from django_tenants.utils import get_public_schema_name
diff --git a/src/etools/applications/core/migrations/0001_initial.py b/src/etools/applications/core/migrations/0001_initial.py
index ba2f1ddf65..fd5a882d13 100644
--- a/src/etools/applications/core/migrations/0001_initial.py
+++ b/src/etools/applications/core/migrations/0001_initial.py
@@ -1,7 +1,7 @@
# Generated by Django 2.0.9 on 2018-10-16 10:47
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
diff --git a/src/etools/applications/core/tests/cases.py b/src/etools/applications/core/tests/cases.py
index 41236bfcf8..7c9033c293 100644
--- a/src/etools/applications/core/tests/cases.py
+++ b/src/etools/applications/core/tests/cases.py
@@ -1,10 +1,10 @@
from django.core.exceptions import ObjectDoesNotExist
from django.core.management import call_command
-from django.urls import resolve
from django.db import connection
-from django_tenants.test.cases import TenantTestCase
-from django_tenants.utils import get_tenant_model, get_tenant_domain_model
+from django.urls import resolve
+from django_tenants.test.cases import TenantTestCase
+from django_tenants.utils import get_tenant_domain_model, get_tenant_model
from rest_framework.test import APIClient, APIRequestFactory, force_authenticate
from unicef_notification.models import EmailTemplate
diff --git a/src/etools/applications/core/tests/test_middleware.py b/src/etools/applications/core/tests/test_middleware.py
index 340812a957..2cbb0d6095 100644
--- a/src/etools/applications/core/tests/test_middleware.py
+++ b/src/etools/applications/core/tests/test_middleware.py
@@ -3,8 +3,8 @@
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
-from django.urls import reverse
from django.test import override_settings, RequestFactory, TestCase
+from django.urls import reverse
from etools.applications.core.middleware import ANONYMOUS_ALLOWED_URL_FRAGMENTS, EToolsTenantMiddleware
from etools.applications.users.tests.factories import CountryFactory, UserFactory
diff --git a/src/etools/applications/environment/tests/test_views.py b/src/etools/applications/environment/tests/test_views.py
index c6b054a917..e5df263a52 100644
--- a/src/etools/applications/environment/tests/test_views.py
+++ b/src/etools/applications/environment/tests/test_views.py
@@ -6,8 +6,8 @@
from rest_framework import status
-from etools.applications.environment.tests.factories import TenantFlagFactory, TenantSwitchFactory
from etools.applications.core.tests.cases import BaseTenantTestCase
+from etools.applications.environment.tests.factories import TenantFlagFactory, TenantSwitchFactory
from etools.applications.users.tests.factories import CountryFactory, UserFactory
diff --git a/src/etools/applications/firms/tests/test_utils.py b/src/etools/applications/firms/tests/test_utils.py
index 1692329b6f..2490f26791 100644
--- a/src/etools/applications/firms/tests/test_utils.py
+++ b/src/etools/applications/firms/tests/test_utils.py
@@ -1,7 +1,6 @@
from django.test import SimpleTestCase
-
from etools.applications.firms.utils import generate_username
diff --git a/src/etools/applications/funds/admin.py b/src/etools/applications/funds/admin.py
index a2ee585b95..294128ff72 100644
--- a/src/etools/applications/funds/admin.py
+++ b/src/etools/applications/funds/admin.py
@@ -1,7 +1,13 @@
from django.contrib import admin
-from etools.applications.funds.models import (Donor, FundsCommitmentHeader, FundsCommitmentItem,
- FundsReservationHeader, FundsReservationItem, Grant,)
+from etools.applications.funds.models import (
+ Donor,
+ FundsCommitmentHeader,
+ FundsCommitmentItem,
+ FundsReservationHeader,
+ FundsReservationItem,
+ Grant,
+)
class GrantAdmin(admin.ModelAdmin):
diff --git a/src/etools/applications/funds/serializers.py b/src/etools/applications/funds/serializers.py
index dc615e3148..33735c5787 100644
--- a/src/etools/applications/funds/serializers.py
+++ b/src/etools/applications/funds/serializers.py
@@ -1,8 +1,14 @@
from rest_framework import serializers
-from etools.applications.funds.models import (Donor, FundsCommitmentHeader, FundsCommitmentItem,
- FundsReservationHeader, FundsReservationItem, Grant,)
+from etools.applications.funds.models import (
+ Donor,
+ FundsCommitmentHeader,
+ FundsCommitmentItem,
+ FundsReservationHeader,
+ FundsReservationItem,
+ Grant,
+)
class FRLineItemSerializer(serializers.ModelSerializer):
diff --git a/src/etools/applications/funds/tests/test_api.py b/src/etools/applications/funds/tests/test_api.py
index dd4aeea1e6..30d9848d60 100644
--- a/src/etools/applications/funds/tests/test_api.py
+++ b/src/etools/applications/funds/tests/test_api.py
@@ -1,17 +1,21 @@
# Python imports
-from django.urls import reverse
from django.test import SimpleTestCase
-
+from django.urls import reverse
from rest_framework import status
from tablib.core import Dataset
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.core.tests.mixins import URLAssertionMixin
-from etools.applications.funds.tests.factories import (DonorFactory, FundsCommitmentHeaderFactory,
- FundsCommitmentItemFactory, FundsReservationHeaderFactory,
- FundsReservationItemFactory, GrantFactory,)
+from etools.applications.funds.tests.factories import (
+ DonorFactory,
+ FundsCommitmentHeaderFactory,
+ FundsCommitmentItemFactory,
+ FundsReservationHeaderFactory,
+ FundsReservationItemFactory,
+ GrantFactory,
+)
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/funds/tests/test_models.py b/src/etools/applications/funds/tests/test_models.py
index d1ec13f640..e207a76740 100644
--- a/src/etools/applications/funds/tests/test_models.py
+++ b/src/etools/applications/funds/tests/test_models.py
@@ -2,9 +2,14 @@
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.funds.models import FundsCommitmentItem, FundsReservationHeader, FundsReservationItem
-from etools.applications.funds.tests.factories import (DonorFactory, FundsCommitmentHeaderFactory,
- FundsCommitmentItemFactory, FundsReservationHeaderFactory,
- FundsReservationItemFactory, GrantFactory,)
+from etools.applications.funds.tests.factories import (
+ DonorFactory,
+ FundsCommitmentHeaderFactory,
+ FundsCommitmentItemFactory,
+ FundsReservationHeaderFactory,
+ FundsReservationItemFactory,
+ GrantFactory,
+)
class TestStrUnicode(BaseTenantTestCase):
diff --git a/src/etools/applications/funds/tests/test_synchronizers.py b/src/etools/applications/funds/tests/test_synchronizers.py
index fd28dabc34..741d152baf 100644
--- a/src/etools/applications/funds/tests/test_synchronizers.py
+++ b/src/etools/applications/funds/tests/test_synchronizers.py
@@ -4,12 +4,20 @@
from decimal import Decimal
from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.funds.models import (FundsCommitmentHeader, FundsCommitmentItem,
- FundsReservationHeader, FundsReservationItem,)
-from etools.applications.funds.tests.factories import (FundsCommitmentHeaderFactory, FundsCommitmentItemFactory,
- FundsReservationHeaderFactory, FundsReservationItemFactory,)
-from etools.applications.users.models import Country
from etools.applications.funds import synchronizers
+from etools.applications.funds.models import (
+ FundsCommitmentHeader,
+ FundsCommitmentItem,
+ FundsReservationHeader,
+ FundsReservationItem,
+)
+from etools.applications.funds.tests.factories import (
+ FundsCommitmentHeaderFactory,
+ FundsCommitmentItemFactory,
+ FundsReservationHeaderFactory,
+ FundsReservationItemFactory,
+)
+from etools.applications.users.models import Country
class TestFundReservationsSynchronizer(BaseTenantTestCase):
diff --git a/src/etools/applications/funds/tests/test_views.py b/src/etools/applications/funds/tests/test_views.py
index 5b3391fc96..3fb30a021c 100644
--- a/src/etools/applications/funds/tests/test_views.py
+++ b/src/etools/applications/funds/tests/test_views.py
@@ -13,11 +13,7 @@
FundsReservationItemFactory,
GrantFactory,
)
-from etools.applications.partners.tests.factories import (
- AgreementFactory,
- InterventionFactory,
- PartnerFactory,
-)
+from etools.applications.partners.tests.factories import AgreementFactory, InterventionFactory, PartnerFactory
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/funds/urls.py b/src/etools/applications/funds/urls.py
index 1ad9348954..e430ab876e 100644
--- a/src/etools/applications/funds/urls.py
+++ b/src/etools/applications/funds/urls.py
@@ -1,9 +1,15 @@
from django.conf.urls import url
-from etools.applications.funds.views import (DonorListAPIView, FRsView, FundsCommitmentHeaderListAPIView,
- FundsCommitmentItemListAPIView, FundsReservationHeaderListAPIView,
- FundsReservationItemListAPIView, GrantListAPIView,)
+from etools.applications.funds.views import (
+ DonorListAPIView,
+ FRsView,
+ FundsCommitmentHeaderListAPIView,
+ FundsCommitmentItemListAPIView,
+ FundsReservationHeaderListAPIView,
+ FundsReservationItemListAPIView,
+ GrantListAPIView,
+)
app_name = 'funds'
urlpatterns = (
diff --git a/src/etools/applications/hact/management/commands/freeze_hact_data.py b/src/etools/applications/hact/management/commands/freeze_hact_data.py
index 9524e4e920..321bc60a43 100644
--- a/src/etools/applications/hact/management/commands/freeze_hact_data.py
+++ b/src/etools/applications/hact/management/commands/freeze_hact_data.py
@@ -4,11 +4,11 @@
from django.core.management import BaseCommand
from django.db import transaction
-from etools.libraries.pythonlib.encoders import CustomJSONEncoder
from etools.applications.core.util_scripts import set_country
from etools.applications.hact.models import HactHistory
from etools.applications.partners.models import hact_default, PartnerOrganization, PlannedEngagement
from etools.applications.users.models import Country
+from etools.libraries.pythonlib.encoders import CustomJSONEncoder
class Command(BaseCommand):
diff --git a/src/etools/applications/hact/models.py b/src/etools/applications/hact/models.py
index fb088836c2..b4ccd19c29 100644
--- a/src/etools/applications/hact/models.py
+++ b/src/etools/applications/hact/models.py
@@ -11,9 +11,9 @@
from model_utils.models import TimeStampedModel
from etools.applications.audit.models import Audit, Engagement, MicroAssessment, SpecialAudit, SpotCheck
-from etools.libraries.pythonlib.encoders import CustomJSONEncoder
from etools.applications.partners.models import PartnerOrganization, PartnerType
from etools.libraries.pythonlib.datetime import get_current_year
+from etools.libraries.pythonlib.encoders import CustomJSONEncoder
class HactHistory(TimeStampedModel):
diff --git a/src/etools/applications/permissions2/models.py b/src/etools/applications/permissions2/models.py
index 674da9d0c3..989515836e 100644
--- a/src/etools/applications/permissions2/models.py
+++ b/src/etools/applications/permissions2/models.py
@@ -2,7 +2,6 @@
from django.contrib.postgres.fields import ArrayField
from django.db import models
-
from model_utils import Choices
from .conditions import BaseCondition
diff --git a/src/etools/applications/vision/tasks.py b/src/etools/applications/vision/tasks.py
index 7e9732df8f..da84599449 100644
--- a/src/etools/applications/vision/tasks.py
+++ b/src/etools/applications/vision/tasks.py
@@ -3,8 +3,8 @@
from celery.utils.log import get_task_logger
-from etools.applications.funds.synchronizers import FundReservationsSynchronizer, FundCommitmentSynchronizer
-from etools.applications.partners.synchronizers import PartnerSynchronizer, DirectCashTransferSynchronizer
+from etools.applications.funds.synchronizers import FundCommitmentSynchronizer, FundReservationsSynchronizer
+from etools.applications.partners.synchronizers import DirectCashTransferSynchronizer, PartnerSynchronizer
from etools.applications.reports.synchronizers import ProgrammeSynchronizer, RAMSynchronizer
from etools.applications.users.models import Country
from etools.applications.vision.exceptions import VisionException
diff --git a/src/etools/applications/vision/tests/test_synchronizers.py b/src/etools/applications/vision/tests/test_synchronizers.py
index daeeed2358..89d8443bb2 100644
--- a/src/etools/applications/vision/tests/test_synchronizers.py
+++ b/src/etools/applications/vision/tests/test_synchronizers.py
@@ -9,8 +9,11 @@
from etools.applications.vision.exceptions import VisionException
from etools.applications.vision.models import VisionSyncLog
from etools.applications.vision.synchronizers import ManualDataLoader
-from etools.applications.vision.vision_data_synchronizer import (VISION_NO_DATA_MESSAGE, VisionDataLoader,
- VisionDataSynchronizer,)
+from etools.applications.vision.vision_data_synchronizer import (
+ VISION_NO_DATA_MESSAGE,
+ VisionDataLoader,
+ VisionDataSynchronizer,
+)
FAUX_VISION_URL = 'https://api.example.com/foo.svc/'
FAUX_VISION_USER = 'jane_user'
From 8c60b54de30883bf9178ceccf407c00a42d1218c Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Mon, 22 Apr 2019 11:09:46 -0400
Subject: [PATCH 59/79] isort
---
.isort.cfg | 2 +-
runtests.sh | 1 +
src/etools/applications/partners/admin.py | 2 +-
src/etools/applications/partners/exports.py | 2 +-
.../applications/partners/permissions.py | 1 +
.../partners/serializers/interventions_v2.py | 2 +-
.../serializers/partner_organization_v2.py | 2 +-
.../partners/serializers/prp_v1.py | 22 +++++++++++-----
.../applications/partners/tests/test_admin.py | 6 +----
.../applications/partners/tests/test_api.py | 14 ++++++++---
.../partners/tests/test_api_agreements.py | 2 +-
.../partners/tests/test_api_dashboards.py | 2 +-
.../partners/tests/test_api_interventions.py | 4 +--
.../partners/tests/test_api_partners.py | 6 +----
.../partners/tests/test_api_pmp.py | 2 +-
.../partners/tests/test_serializers.py | 13 +++++++---
.../tests/test_serializers_intervention.py | 2 +-
.../applications/partners/tests/test_utils.py | 25 +++++--------------
.../tests/test_validation_agreements.py | 4 +--
.../tests/test_validation_interventions.py | 15 +++--------
src/etools/applications/partners/urls_v2.py | 2 +-
.../partners/validation/agreements.py | 11 +++-----
.../partners/validation/interventions.py | 12 +++------
.../partners/views/agreements_v2.py | 2 +-
.../applications/partners/views/dashboards.py | 16 ++----------
.../partners/views/interventions_v2.py | 16 +++++++++++-
.../partners/views/partner_organization_v2.py | 2 +-
.../applications/partners/views/prp_v1.py | 12 +++++----
src/etools/applications/partners/views/v1.py | 2 +-
src/etools/config/sentry.py | 7 +++---
30 files changed, 100 insertions(+), 111 deletions(-)
diff --git a/.isort.cfg b/.isort.cfg
index 4890e36deb..b6def00452 100644
--- a/.isort.cfg
+++ b/.isort.cfg
@@ -6,7 +6,7 @@ known_django = django
sections = FUTURE,STDLIB,DJANGO,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
known_first_party = etools
multi_line_output = 3
-line_length = 119
+line_length = 120
balanced_wrapping = true
order_by_type = false
not_skip = __init__.py
diff --git a/runtests.sh b/runtests.sh
index 27e63b366d..de46b7ebd5 100755
--- a/runtests.sh
+++ b/runtests.sh
@@ -15,6 +15,7 @@ python -W ignore manage.py makemigrations --dry-run --check
# Check code style unless running under tox, in which case tox runs flake8 separately
if [[ $RUNNING_UNDER_TOX != 1 ]] ; then
time flake8 src/
+ # time isort -rc src/ --check-only
fi
# Run unittests and coverage report
diff --git a/src/etools/applications/partners/admin.py b/src/etools/applications/partners/admin.py
index ca86a1306c..a0329afe79 100644
--- a/src/etools/applications/partners/admin.py
+++ b/src/etools/applications/partners/admin.py
@@ -13,9 +13,9 @@
from etools.applications.partners.exports import PartnerExport
from etools.applications.partners.forms import ( # TODO intervention sector locations cleanup
+ InterventionAttachmentForm,
PartnersAdminForm,
PartnerStaffMemberForm,
- InterventionAttachmentForm,
)
from etools.applications.partners.mixins import CountryUsersAdminMixin, HiddenPartnerMixin
from etools.applications.partners.models import ( # TODO intervention sector locations cleanup
diff --git a/src/etools/applications/partners/exports.py b/src/etools/applications/partners/exports.py
index 0988b8a908..cfe454f9bd 100644
--- a/src/etools/applications/partners/exports.py
+++ b/src/etools/applications/partners/exports.py
@@ -1,6 +1,6 @@
from import_export import resources
-from etools.applications.partners.models import PartnerOrganization, Intervention
+from etools.applications.partners.models import Intervention, PartnerOrganization
class PartnerExport(resources.ModelResource):
diff --git a/src/etools/applications/partners/permissions.py b/src/etools/applications/partners/permissions.py
index 9ba68582e6..6800bb5c14 100644
--- a/src/etools/applications/partners/permissions.py
+++ b/src/etools/applications/partners/permissions.py
@@ -1,4 +1,5 @@
import datetime
+
from django.apps import apps
from django.utils.lru_cache import lru_cache
from django.utils.translation import ugettext as _
diff --git a/src/etools/applications/partners/serializers/interventions_v2.py b/src/etools/applications/partners/serializers/interventions_v2.py
index b15185cc85..211ee7a5e8 100644
--- a/src/etools/applications/partners/serializers/interventions_v2.py
+++ b/src/etools/applications/partners/serializers/interventions_v2.py
@@ -1,4 +1,4 @@
-from datetime import datetime, date
+from datetime import date, datetime
from operator import itemgetter
from django.db import transaction
diff --git a/src/etools/applications/partners/serializers/partner_organization_v2.py b/src/etools/applications/partners/serializers/partner_organization_v2.py
index f936931648..b155892d06 100644
--- a/src/etools/applications/partners/serializers/partner_organization_v2.py
+++ b/src/etools/applications/partners/serializers/partner_organization_v2.py
@@ -22,8 +22,8 @@
PlannedEngagement,
)
from etools.applications.partners.serializers.interventions_v2 import (
- InterventionMonitorSerializer,
InterventionListSerializer,
+ InterventionMonitorSerializer,
)
diff --git a/src/etools/applications/partners/serializers/prp_v1.py b/src/etools/applications/partners/serializers/prp_v1.py
index aaefeb435e..6fb6b2ea89 100644
--- a/src/etools/applications/partners/serializers/prp_v1.py
+++ b/src/etools/applications/partners/serializers/prp_v1.py
@@ -4,13 +4,23 @@
from rest_framework import serializers
from unicef_attachments.fields import AttachmentSingleFileField
-
from unicef_locations.models import Location
-from etools.applications.partners.models import (Intervention, InterventionAmendment,
- PartnerOrganization, PartnerStaffMember,)
-from etools.applications.reports.models import (AppliedIndicator, Disaggregation,
- DisaggregationValue, LowerResult, Result, ReportingRequirement,
- SpecialReportingRequirement)
+
+from etools.applications.partners.models import (
+ Intervention,
+ InterventionAmendment,
+ PartnerOrganization,
+ PartnerStaffMember,
+)
+from etools.applications.reports.models import (
+ AppliedIndicator,
+ Disaggregation,
+ DisaggregationValue,
+ LowerResult,
+ ReportingRequirement,
+ Result,
+ SpecialReportingRequirement,
+)
from etools.applications.reports.serializers.v1 import SectionSerializer
diff --git a/src/etools/applications/partners/tests/test_admin.py b/src/etools/applications/partners/tests/test_admin.py
index bbbe408968..42254bdbbb 100644
--- a/src/etools/applications/partners/tests/test_admin.py
+++ b/src/etools/applications/partners/tests/test_admin.py
@@ -5,11 +5,7 @@
from unicef_snapshot.models import Activity
from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.partners.admin import (
- AgreementAdmin,
- InterventionAdmin,
- PartnerStaffMemberAdmin,
-)
+from etools.applications.partners.admin import AgreementAdmin, InterventionAdmin, PartnerStaffMemberAdmin
from etools.applications.partners.models import Agreement, Intervention, PartnerStaffMember
from etools.applications.partners.tests.factories import (
AgreementFactory,
diff --git a/src/etools/applications/partners/tests/test_api.py b/src/etools/applications/partners/tests/test_api.py
index 567e25e31c..d04a7b582d 100644
--- a/src/etools/applications/partners/tests/test_api.py
+++ b/src/etools/applications/partners/tests/test_api.py
@@ -3,10 +3,16 @@
from django.urls import reverse
from etools.applications.core.tests.cases import BaseTenantTestCase
-from etools.applications.partners.models import PartnerType, PartnerOrganization
-from etools.applications.partners.tests.factories import (AgreementFactory, AgreementAmendmentFactory, PartnerFactory, InterventionFactory,
- InterventionAmendmentFactory, InterventionResultLinkFactory)
-from etools.libraries.tests.api_checker import ApiCheckerMixin, ViewSetChecker, AssertTimeStampedMixin
+from etools.applications.partners.models import PartnerOrganization, PartnerType
+from etools.applications.partners.tests.factories import (
+ AgreementAmendmentFactory,
+ AgreementFactory,
+ InterventionAmendmentFactory,
+ InterventionFactory,
+ InterventionResultLinkFactory,
+ PartnerFactory,
+)
+from etools.libraries.tests.api_checker import ApiCheckerMixin, AssertTimeStampedMixin, ViewSetChecker
class TestAPIAgreements(ApiCheckerMixin, AssertTimeStampedMixin, BaseTenantTestCase):
diff --git a/src/etools/applications/partners/tests/test_api_agreements.py b/src/etools/applications/partners/tests/test_api_agreements.py
index a074bb0ba1..74a04a28b9 100644
--- a/src/etools/applications/partners/tests/test_api_agreements.py
+++ b/src/etools/applications/partners/tests/test_api_agreements.py
@@ -1,10 +1,10 @@
import datetime
import json
-import mock
from django.test import SimpleTestCase
from django.urls import reverse
+import mock
from rest_framework import status
from unicef_attachments.models import Attachment
from unicef_snapshot.models import Activity
diff --git a/src/etools/applications/partners/tests/test_api_dashboards.py b/src/etools/applications/partners/tests/test_api_dashboards.py
index 71a6f03441..76b5d7dca9 100644
--- a/src/etools/applications/partners/tests/test_api_dashboards.py
+++ b/src/etools/applications/partners/tests/test_api_dashboards.py
@@ -15,7 +15,7 @@
InterventionFactory,
)
from etools.applications.t2f.models import Travel, TravelType
-from etools.applications.t2f.tests.factories import TravelFactory, TravelActivityFactory
+from etools.applications.t2f.tests.factories import TravelActivityFactory, TravelFactory
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/partners/tests/test_api_interventions.py b/src/etools/applications/partners/tests/test_api_interventions.py
index a11a431a37..fdde3237e7 100644
--- a/src/etools/applications/partners/tests/test_api_interventions.py
+++ b/src/etools/applications/partners/tests/test_api_interventions.py
@@ -18,10 +18,10 @@
from etools.applications.attachments.models import AttachmentFlat
from etools.applications.attachments.tests.factories import AttachmentFactory, AttachmentFileTypeFactory
-from etools.applications.environment.helpers import tenant_switch_is_active
-from etools.applications.environment.tests.factories import TenantSwitchFactory
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.core.tests.mixins import URLAssertionMixin
+from etools.applications.environment.helpers import tenant_switch_is_active
+from etools.applications.environment.tests.factories import TenantSwitchFactory
from etools.applications.partners.models import Intervention, InterventionAmendment, InterventionResultLink
from etools.applications.partners.permissions import InterventionPermissions
from etools.applications.partners.tests.factories import (
diff --git a/src/etools/applications/partners/tests/test_api_partners.py b/src/etools/applications/partners/tests/test_api_partners.py
index 668bb800a4..3d32f53d02 100644
--- a/src/etools/applications/partners/tests/test_api_partners.py
+++ b/src/etools/applications/partners/tests/test_api_partners.py
@@ -34,11 +34,7 @@
)
from etools.applications.partners.views.partner_organization_v2 import PartnerOrganizationAddView
from etools.applications.reports.models import ResultType
-from etools.applications.reports.tests.factories import (
- CountryProgrammeFactory,
- ResultFactory,
- ResultTypeFactory,
-)
+from etools.applications.reports.tests.factories import CountryProgrammeFactory, ResultFactory, ResultTypeFactory
from etools.applications.t2f.tests.factories import TravelActivityFactory
from etools.applications.users.tests.factories import GroupFactory, UserFactory
diff --git a/src/etools/applications/partners/tests/test_api_pmp.py b/src/etools/applications/partners/tests/test_api_pmp.py
index 95782af5a0..a5dba0c4ec 100644
--- a/src/etools/applications/partners/tests/test_api_pmp.py
+++ b/src/etools/applications/partners/tests/test_api_pmp.py
@@ -3,8 +3,8 @@
from django.test import SimpleTestCase
from django.urls import reverse
-from django_tenants.test.client import TenantClient
+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
diff --git a/src/etools/applications/partners/tests/test_serializers.py b/src/etools/applications/partners/tests/test_serializers.py
index 32b8e87f1a..09c41999fd 100644
--- a/src/etools/applications/partners/tests/test_serializers.py
+++ b/src/etools/applications/partners/tests/test_serializers.py
@@ -1,16 +1,21 @@
# Python imports
import datetime
-
from unittest import skip
+
from rest_framework import serializers
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import Agreement, PartnerType
from etools.applications.partners.serializers.agreements_v2 import AgreementCreateUpdateSerializer
from etools.applications.partners.serializers.partner_organization_v2 import PartnerOrganizationDetailSerializer
-from etools.applications.partners.tests.factories import (AgreementAmendmentFactory, AgreementFactory,
- InterventionFactory, PartnerFactory, PartnerStaffFactory,
- PlannedEngagementFactory,)
+from etools.applications.partners.tests.factories import (
+ AgreementAmendmentFactory,
+ AgreementFactory,
+ InterventionFactory,
+ PartnerFactory,
+ PartnerStaffFactory,
+ PlannedEngagementFactory,
+)
from etools.applications.reports.tests.factories import CountryProgrammeFactory
from etools.applications.users.tests.factories import UserFactory
diff --git a/src/etools/applications/partners/tests/test_serializers_intervention.py b/src/etools/applications/partners/tests/test_serializers_intervention.py
index 4e2e6ec165..7606ffbc8a 100644
--- a/src/etools/applications/partners/tests/test_serializers_intervention.py
+++ b/src/etools/applications/partners/tests/test_serializers_intervention.py
@@ -5,7 +5,7 @@
from etools.applications.partners.serializers.interventions_v2 import InterventionReportingRequirementCreateSerializer
from etools.applications.partners.tests.factories import InterventionFactory, InterventionResultLinkFactory
from etools.applications.reports.models import ReportingRequirement
-from etools.applications.reports.tests.factories import (AppliedIndicatorFactory, LowerResultFactory)
+from etools.applications.reports.tests.factories import AppliedIndicatorFactory, LowerResultFactory
class TestInterventionReportingRequirementCreateSerializer(BaseTenantTestCase):
diff --git a/src/etools/applications/partners/tests/test_utils.py b/src/etools/applications/partners/tests/test_utils.py
index 84d8585def..2207591e70 100644
--- a/src/etools/applications/partners/tests/test_utils.py
+++ b/src/etools/applications/partners/tests/test_utils.py
@@ -1,32 +1,19 @@
import datetime
-from mock import Mock, patch
from django.conf import settings
from django.core.management import call_command
from django.utils import timezone
+from mock import Mock, patch
+from unicef_locations.tests.factories import GatewayTypeFactory, LocationFactory
+
from etools.applications.attachments.tests.factories import AttachmentFileTypeFactory
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.funds.tests.factories import FundsReservationHeaderFactory
-from unicef_locations.tests.factories import GatewayTypeFactory, LocationFactory
from etools.applications.partners import utils
-from etools.applications.partners.models import (
- Agreement,
- Intervention,
- InterventionBudget,
- InterventionResultLink,
-)
-from etools.applications.partners.tests.factories import (
- AgreementFactory,
- InterventionFactory,
- PartnerFactory,
-)
-from etools.applications.reports.models import (
- AppliedIndicator,
- IndicatorBlueprint,
- LowerResult,
- ResultType,
-)
+from etools.applications.partners.models import Agreement, Intervention, InterventionBudget, InterventionResultLink
+from etools.applications.partners.tests.factories import AgreementFactory, InterventionFactory, PartnerFactory
+from etools.applications.reports.models import AppliedIndicator, IndicatorBlueprint, LowerResult, ResultType
from etools.applications.reports.tests.factories import CountryProgrammeFactory, ResultFactory
from etools.applications.users.tests.factories import GroupFactory, UserFactory
diff --git a/src/etools/applications/partners/tests/test_validation_agreements.py b/src/etools/applications/partners/tests/test_validation_agreements.py
index 4741304ad3..7e56764665 100644
--- a/src/etools/applications/partners/tests/test_validation_agreements.py
+++ b/src/etools/applications/partners/tests/test_validation_agreements.py
@@ -1,7 +1,8 @@
import datetime
-
from unittest import skip
+from etools_validator.exceptions import BasicValidationError, TransitionError
+
from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import Agreement
from etools.applications.partners.tests.factories import (
@@ -13,7 +14,6 @@
from etools.applications.partners.validation import agreements
from etools.applications.reports.tests.factories import CountryProgrammeFactory
from etools.applications.users.tests.factories import UserFactory
-from etools_validator.exceptions import BasicValidationError, TransitionError
class TestAgreementTransitionToSignedValid(BaseTenantTestCase):
diff --git a/src/etools/applications/partners/tests/test_validation_interventions.py b/src/etools/applications/partners/tests/test_validation_interventions.py
index c01794aa44..fbaecd7a16 100644
--- a/src/etools/applications/partners/tests/test_validation_interventions.py
+++ b/src/etools/applications/partners/tests/test_validation_interventions.py
@@ -1,17 +1,13 @@
import datetime
from unittest import skip
+from etools_validator.exceptions import BasicValidationError, StateValidationError, TransitionError
from mock import Mock, patch
-from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.attachments.tests.factories import AttachmentFactory
+from etools.applications.core.tests.cases import BaseTenantTestCase
from etools.applications.funds.tests.factories import FundsReservationHeaderFactory
-from etools.applications.partners.models import (
- Agreement,
- FileType,
- Intervention,
- InterventionAmendment,
-)
+from etools.applications.partners.models import Agreement, FileType, Intervention, InterventionAmendment
from etools.applications.partners.tests.factories import (
AgreementFactory,
FileTypeFactory,
@@ -35,11 +31,6 @@
transition_to_terminated,
)
from etools.applications.users.tests.factories import GroupFactory, UserFactory
-from etools_validator.exceptions import (
- BasicValidationError,
- StateValidationError,
- TransitionError,
-)
class TestPartnershipManagerOnly(BaseTenantTestCase):
diff --git a/src/etools/applications/partners/urls_v2.py b/src/etools/applications/partners/urls_v2.py
index 2b2fc488df..b667d35a36 100644
--- a/src/etools/applications/partners/urls_v2.py
+++ b/src/etools/applications/partners/urls_v2.py
@@ -39,8 +39,8 @@
PartnerNotProgrammaticVisitCompliant,
PartnerNotSpotCheckCompliant,
PartnerOrganizationAddView,
- PartnerOrganizationAssessmentUpdateDeleteView,
PartnerOrganizationAssessmentListCreateView,
+ PartnerOrganizationAssessmentUpdateDeleteView,
PartnerOrganizationDashboardAPIView,
PartnerOrganizationDeleteView,
PartnerOrganizationDetailAPIView,
diff --git a/src/etools/applications/partners/validation/agreements.py b/src/etools/applications/partners/validation/agreements.py
index 34387e6673..ac48b6c852 100644
--- a/src/etools/applications/partners/validation/agreements.py
+++ b/src/etools/applications/partners/validation/agreements.py
@@ -3,15 +3,12 @@
from django.utils.translation import ugettext as _
-from etools.applications.partners.permissions import AgreementPermissions
-from etools_validator.exceptions import (
- BasicValidationError,
- StateValidationError,
- TransitionError,
-)
-from etools_validator.utils import check_rigid_fields, check_required_fields
+from etools_validator.exceptions import BasicValidationError, StateValidationError, TransitionError
+from etools_validator.utils import check_required_fields, check_rigid_fields
from etools_validator.validation import CompleteValidation
+from etools.applications.partners.permissions import AgreementPermissions
+
def agreement_transition_to_signed_valid(agreement):
"""Returns True if it's valid for the agreement to transition to signed, otherwise raises a TransitionError.
diff --git a/src/etools/applications/partners/validation/interventions.py b/src/etools/applications/partners/validation/interventions.py
index 4340398065..d874f77a6e 100644
--- a/src/etools/applications/partners/validation/interventions.py
+++ b/src/etools/applications/partners/validation/interventions.py
@@ -1,18 +1,14 @@
import logging
from datetime import date
-
from django.utils.translation import ugettext as _
+from etools_validator.exceptions import BasicValidationError, StateValidationError, TransitionError
+from etools_validator.utils import check_required_fields, check_rigid_fields
+from etools_validator.validation import CompleteValidation
+
from etools.applications.partners.permissions import InterventionPermissions
from etools.applications.reports.models import AppliedIndicator
-from etools_validator.exceptions import (
- BasicValidationError,
- StateValidationError,
- TransitionError,
-)
-from etools_validator.utils import check_rigid_fields, check_required_fields
-from etools_validator.validation import CompleteValidation
logger = logging.getLogger('partners.interventions.validation')
diff --git a/src/etools/applications/partners/views/agreements_v2.py b/src/etools/applications/partners/views/agreements_v2.py
index 46e05ff879..1a4e04fb24 100644
--- a/src/etools/applications/partners/views/agreements_v2.py
+++ b/src/etools/applications/partners/views/agreements_v2.py
@@ -32,8 +32,8 @@
AgreementExportFlatSerializer,
AgreementExportSerializer,
)
-from etools.applications.partners.validation.agreements import AgreementValid
from etools.applications.partners.utils import send_agreement_suspended_notification
+from etools.applications.partners.validation.agreements import AgreementValid
class AgreementListAPIView(QueryStringFilterMixin, ExportModelMixin, ValidatorViewMixin, ListCreateAPIView):
diff --git a/src/etools/applications/partners/views/dashboards.py b/src/etools/applications/partners/views/dashboards.py
index 0bd9131d30..897d033475 100644
--- a/src/etools/applications/partners/views/dashboards.py
+++ b/src/etools/applications/partners/views/dashboards.py
@@ -1,19 +1,7 @@
import functools
import operator
-from django.db.models import (
- Case,
- CharField,
- Count,
- F,
- Max,
- Min,
- OuterRef,
- Q,
- Subquery,
- Sum,
- When,
-)
+from django.db.models import Case, CharField, Count, F, Max, Min, OuterRef, Q, Subquery, Sum, When
from rest_framework.generics import ListCreateAPIView
from rest_framework.permissions import IsAdminUser
@@ -25,7 +13,7 @@
from etools.applications.partners.exports_v2 import PartnershipDashCSVRenderer
from etools.applications.partners.models import FileType, Intervention, InterventionAttachment
from etools.applications.partners.serializers.dashboards import InterventionDashSerializer
-from etools.applications.t2f.models import Travel, TravelType, TravelActivity
+from etools.applications.t2f.models import Travel, TravelActivity, TravelType
class InterventionPartnershipDashView(QueryStringFilterMixin, ListCreateAPIView):
diff --git a/src/etools/applications/partners/views/interventions_v2.py b/src/etools/applications/partners/views/interventions_v2.py
index 54747e4881..49b0866ce4 100644
--- a/src/etools/applications/partners/views/interventions_v2.py
+++ b/src/etools/applications/partners/views/interventions_v2.py
@@ -650,7 +650,7 @@ def sort_key(self):
)
-class InterventionLocationListAPIView(ListAPIView):
+class InterventionLocationListAPIView(QueryStringFilterMixin, ListAPIView):
"""
API to export a list of intervention locations.
@@ -668,6 +668,20 @@ class InterventionLocationListAPIView(ListAPIView):
InterventionLocationCSVRenderer,
)
+ filters = (
+ ('sections', 'sections__in'),
+ ('country_programmes', 'country_programme__in'),
+ ('status', 'status__in'),
+ ('partners', 'agreement__partner__in'),
+ ('offices', 'offices__in'),
+ ('results', 'result_links__cp_output__in'),
+ ('donors', 'frs__fr_items__donor__in'),
+ ('grants', 'frs__fr_items__grant_number__in'),
+ ('unicef_focal_points', 'unicef_focal_points__in'),
+ ('interventions', 'pk__in'),
+ ('clusters', 'result_links__ll_results__applied_indicators__cluster_name__icontains'),
+ )
+
def list(self, request, *args, **kwargs):
rows = []
for intervention in self.get_queryset():
diff --git a/src/etools/applications/partners/views/partner_organization_v2.py b/src/etools/applications/partners/views/partner_organization_v2.py
index 2c636100ba..a5fe6bd299 100644
--- a/src/etools/applications/partners/views/partner_organization_v2.py
+++ b/src/etools/applications/partners/views/partner_organization_v2.py
@@ -72,8 +72,8 @@
from etools.applications.partners.synchronizers import PartnerSynchronizer
from etools.applications.partners.views.helpers import set_tenant_or_fail
from etools.applications.t2f.models import Travel, TravelActivity, TravelType
-from etools.libraries.djangolib.models import StringConcat
from etools.applications.vision.utils import get_data_from_insight
+from etools.libraries.djangolib.models import StringConcat
class PartnerOrganizationListAPIView(QueryStringFilterMixin, ExportModelMixin, ListCreateAPIView):
diff --git a/src/etools/applications/partners/views/prp_v1.py b/src/etools/applications/partners/views/prp_v1.py
index 6fae616e7e..d498783589 100644
--- a/src/etools/applications/partners/views/prp_v1.py
+++ b/src/etools/applications/partners/views/prp_v1.py
@@ -3,17 +3,19 @@
from django.db.models import Q
-from rest_framework.generics import ListAPIView, get_object_or_404
+from rest_framework.generics import get_object_or_404, ListAPIView
+from rest_framework.pagination import LimitOffsetPagination
from rest_framework.response import Response
from rest_framework.views import APIView
-from rest_framework.pagination import LimitOffsetPagination
-
from etools.applications.partners.filters import PartnerScopeFilter
from etools.applications.partners.models import Intervention, PartnerOrganization
from etools.applications.partners.permissions import ListCreateAPIMixedPermission, ReadOnlyAPIUser
-from etools.applications.partners.serializers.prp_v1 import PRPInterventionListSerializer, \
- PRPPartnerOrganizationListSerializer, InterventionPDFileSerializer
+from etools.applications.partners.serializers.prp_v1 import (
+ InterventionPDFileSerializer,
+ PRPInterventionListSerializer,
+ PRPPartnerOrganizationListSerializer,
+)
from etools.applications.partners.views.helpers import set_tenant_or_fail
diff --git a/src/etools/applications/partners/views/v1.py b/src/etools/applications/partners/views/v1.py
index 9a21cceda8..bd70801100 100644
--- a/src/etools/applications/partners/views/v1.py
+++ b/src/etools/applications/partners/views/v1.py
@@ -1,10 +1,10 @@
from collections import namedtuple
from django.conf import settings
+from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django.utils.http import urlsafe_base64_decode
from django.views.generic import TemplateView, View
-from django.contrib.auth.mixins import LoginRequiredMixin
from easy_pdf.views import PDFTemplateView
from rest_framework import mixins, viewsets
diff --git a/src/etools/config/sentry.py b/src/etools/config/sentry.py
index 43274527ed..a7f92dd158 100644
--- a/src/etools/config/sentry.py
+++ b/src/etools/config/sentry.py
@@ -1,12 +1,11 @@
-import sentry_sdk
+from django.conf import settings
+from django.db import connection
+import sentry_sdk
from sentry_sdk import configure_scope
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.django import DjangoIntegration
-from django.db import connection
-from django.conf import settings
-
if hasattr(settings, 'SENTRY_DSN'):
def before_send(event, hint):
with configure_scope() as scope:
From 220c9456d25a3e0bf59c582113652d067dddc4c3 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Tue, 23 Apr 2019 11:44:09 -0400
Subject: [PATCH 60/79] added missing filters
---
.../partners/views/interventions_v2.py | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/etools/applications/partners/views/interventions_v2.py b/src/etools/applications/partners/views/interventions_v2.py
index 49b0866ce4..a8f3f023ee 100644
--- a/src/etools/applications/partners/views/interventions_v2.py
+++ b/src/etools/applications/partners/views/interventions_v2.py
@@ -669,17 +669,24 @@ class InterventionLocationListAPIView(QueryStringFilterMixin, ListAPIView):
)
filters = (
+ ('status', 'status__in'),
+ ('document_type', 'document_type__in'),
('sections', 'sections__in'),
+ ('office', 'offices__in'),
('country_programmes', 'country_programme__in'),
- ('status', 'status__in'),
- ('partners', 'agreement__partner__in'),
- ('offices', 'offices__in'),
- ('results', 'result_links__cp_output__in'),
('donors', 'frs__fr_items__donor__in'),
('grants', 'frs__fr_items__grant_number__in'),
+ ('results', 'result_links__cp_output__in'),
('unicef_focal_points', 'unicef_focal_points__in'),
('interventions', 'pk__in'),
- ('clusters', 'result_links__ll_results__applied_indicators__cluster_name__icontains'),
+ ('cp_outputs', 'result_links__cp_output__in'),
+ ('cluster', 'result_links__ll_results__applied_indicators__cluster_indicator_title__icontains'),
+ ('unicef_focal_points', 'unicef_focal_points__in'),
+ ('start', 'start__gte'),
+ ('end', 'end__lte'),
+ ('end_after', 'end__gte'),
+ ('location', 'result_links__ll_results__applied_indicators__locations__name__icontains'),
+ ('partners', 'agreement__partner__in'),
)
def list(self, request, *args, **kwargs):
From 2eb7d0eb3ed415940d7cf77f8cd6d88fbe08ec2e Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Tue, 23 Apr 2019 11:04:22 -0400
Subject: [PATCH 61/79] admin audit staff member allow to filter by email
---
src/etools/applications/audit/purchase_order/admin.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/etools/applications/audit/purchase_order/admin.py b/src/etools/applications/audit/purchase_order/admin.py
index 79469be1a4..0c73fd5e58 100644
--- a/src/etools/applications/audit/purchase_order/admin.py
+++ b/src/etools/applications/audit/purchase_order/admin.py
@@ -50,4 +50,4 @@ class PurchaseOrderAdmin(admin.ModelAdmin):
class AuditorStaffAdmin(admin.ModelAdmin):
list_display = ['user', 'auditor_firm', 'hidden']
list_filter = ['auditor_firm', 'hidden']
- search_fields = ['user__username', 'user__first_name', 'user__last_name', 'auditor_firm__name', ]
+ search_fields = ['user__username', 'user__email', 'user__first_name', 'user__last_name', 'auditor_firm__name', ]
From ac32f95eb418adbd2228988ab53e33dce59e10ac Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Tue, 23 Apr 2019 10:59:10 -0400
Subject: [PATCH 62/79] Change yaml load to safe_load to prevent warning
---
src/etools/config/settings/base.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/etools/config/settings/base.py b/src/etools/config/settings/base.py
index 35ecdfec1f..744d430b5d 100644
--- a/src/etools/config/settings/base.py
+++ b/src/etools/config/settings/base.py
@@ -47,7 +47,7 @@ def str2bool(value):
try:
with open(SECRETS_FILE_LOCATION, 'r') as secrets_file:
- SECRETS = yaml.load(secrets_file)['ENVIRONMENT']
+ SECRETS = yaml.safe_load(secrets_file)['ENVIRONMENT']
except FileNotFoundError:
# pass, for now we default trying to get the secrets from env vars as well
SECRETS = {}
From e71ee7e75f3a84a12943f1cdf68bad7c379b3c33 Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Tue, 23 Apr 2019 11:00:49 -0400
Subject: [PATCH 63/79] Update django to 2.1.8 and psycopg2 to 2.8.2
---
Pipfile | 4 +-
Pipfile.lock | 142 +++++++++++++++++++++++++--------------------------
2 files changed, 72 insertions(+), 74 deletions(-)
diff --git a/Pipfile b/Pipfile
index ce9d522f27..30ad470709 100644
--- a/Pipfile
+++ b/Pipfile
@@ -23,7 +23,7 @@ carto = "==1.4"
celery = "==4.3"
dj-database-url = "==0.5"
dj-static = "==0.0.6"
-Django = "==2.1.7"
+Django = "==2.1.8"
django-appconf = "==1.0.3"
django_celery_beat = "==1.4"
django-celery-email = "==2.0.1"
@@ -63,7 +63,7 @@ GDAL = "==2.4.0"
gunicorn = "==19.9"
newrelic = "==2.94.0.79"
Pillow = "==5.4.1"
-psycopg2-binary = "==2.7.7"
+psycopg2-binary = "==2.8.2"
sentry-sdk = "==0.7.10"
redis = "==3.2"
requests = "==2.21"
diff --git a/Pipfile.lock b/Pipfile.lock
index 16666c8608..1756d1f8ec 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "b1872df511fe7116c492e4f6b61490861452a922bd0e6b11049c49dd0c4d1906"
+ "sha256": "ebd440f956d33b04dc1801186a9be40fd9a9cf9158152a12858cab0c3d50d778"
},
"pipfile-spec": 6,
"requires": {
@@ -32,10 +32,10 @@
},
"azure-common": {
"hashes": [
- "sha256:5cb223c1b52deb8ff9304387201bab83950787be9ca2e8733220726740cc40d0",
- "sha256:5fd62ae10b1add97d3c69af970328ec3bd869184396bcf6bfa9c7bc94d688424"
+ "sha256:14722caf6c3ed81d2cfdd3e448635fdc78f214dc6f17558dd1ca5b87bccc0631",
+ "sha256:622d9360a1b61172b4c0d1cc58f939c68402aa19ca44872ab3d224d913aa6d0c"
],
- "version": "==1.1.18"
+ "version": "==1.1.19"
},
"azure-nspkg": {
"hashes": [
@@ -98,36 +98,36 @@
},
"cffi": {
"hashes": [
- "sha256:00b97afa72c233495560a0793cdc86c2571721b4271c0667addc83c417f3d90f",
- "sha256:0ba1b0c90f2124459f6966a10c03794082a2f3985cd699d7d63c4a8dae113e11",
- "sha256:0bffb69da295a4fc3349f2ec7cbe16b8ba057b0a593a92cbe8396e535244ee9d",
- "sha256:21469a2b1082088d11ccd79dd84157ba42d940064abbfa59cf5f024c19cf4891",
- "sha256:2e4812f7fa984bf1ab253a40f1f4391b604f7fc424a3e21f7de542a7f8f7aedf",
- "sha256:2eac2cdd07b9049dd4e68449b90d3ef1adc7c759463af5beb53a84f1db62e36c",
- "sha256:2f9089979d7456c74d21303c7851f158833d48fb265876923edcb2d0194104ed",
- "sha256:3dd13feff00bddb0bd2d650cdb7338f815c1789a91a6f68fdc00e5c5ed40329b",
- "sha256:4065c32b52f4b142f417af6f33a5024edc1336aa845b9d5a8d86071f6fcaac5a",
- "sha256:51a4ba1256e9003a3acf508e3b4f4661bebd015b8180cc31849da222426ef585",
- "sha256:59888faac06403767c0cf8cfb3f4a777b2939b1fbd9f729299b5384f097f05ea",
- "sha256:59c87886640574d8b14910840327f5cd15954e26ed0bbd4e7cef95fa5aef218f",
- "sha256:610fc7d6db6c56a244c2701575f6851461753c60f73f2de89c79bbf1cc807f33",
- "sha256:70aeadeecb281ea901bf4230c6222af0248c41044d6f57401a614ea59d96d145",
- "sha256:71e1296d5e66c59cd2c0f2d72dc476d42afe02aeddc833d8e05630a0551dad7a",
- "sha256:8fc7a49b440ea752cfdf1d51a586fd08d395ff7a5d555dc69e84b1939f7ddee3",
- "sha256:9b5c2afd2d6e3771d516045a6cfa11a8da9a60e3d128746a7fe9ab36dfe7221f",
- "sha256:9c759051ebcb244d9d55ee791259ddd158188d15adee3c152502d3b69005e6bd",
- "sha256:b4d1011fec5ec12aa7cc10c05a2f2f12dfa0adfe958e56ae38dc140614035804",
- "sha256:b4f1d6332339ecc61275bebd1f7b674098a66fea11a00c84d1c58851e618dc0d",
- "sha256:c030cda3dc8e62b814831faa4eb93dd9a46498af8cd1d5c178c2de856972fd92",
- "sha256:c2e1f2012e56d61390c0e668c20c4fb0ae667c44d6f6a2eeea5d7148dcd3df9f",
- "sha256:c37c77d6562074452120fc6c02ad86ec928f5710fbc435a181d69334b4de1d84",
- "sha256:c8149780c60f8fd02752d0429246088c6c04e234b895c4a42e1ea9b4de8d27fb",
- "sha256:cbeeef1dc3c4299bd746b774f019de9e4672f7cc666c777cd5b409f0b746dac7",
- "sha256:e113878a446c6228669144ae8a56e268c91b7f1fafae927adc4879d9849e0ea7",
- "sha256:e21162bf941b85c0cda08224dade5def9360f53b09f9f259adb85fc7dd0e7b35",
- "sha256:fb6934ef4744becbda3143d30c6604718871495a5e36c408431bf33d9c146889"
- ],
- "version": "==1.12.2"
+ "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
+ "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
+ "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
+ "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
+ "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
+ "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
+ "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
+ "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
+ "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
+ "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
+ "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
+ "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
+ "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
+ "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
+ "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
+ "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
+ "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
+ "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
+ "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
+ "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
+ "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
+ "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
+ "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
+ "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
+ "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
+ "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
+ "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
+ "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
+ ],
+ "version": "==1.12.3"
},
"chardet": {
"hashes": [
@@ -205,11 +205,11 @@
},
"django": {
"hashes": [
- "sha256:275bec66fd2588dd517ada59b8bfb23d4a9abc5a362349139ddda3c7ff6f5ade",
- "sha256:939652e9d34d7d53d74d5d8ef82a19e5f8bb2de75618f7e5360691b6e9667963"
+ "sha256:0fd54e4f27bc3e0b7054a11e6b3a18fa53f2373f6b2df8a22e8eadfe018970a5",
+ "sha256:f3b28084101d516f56104856761bc247f85a2a5bbd9da39d9f6197ff461b3ee4"
],
"index": "pypi",
- "version": "==2.1.7"
+ "version": "==2.1.8"
},
"django-appconf": {
"hashes": [
@@ -690,39 +690,37 @@
},
"psycopg2-binary": {
"hashes": [
- "sha256:19a2d1f3567b30f6c2bb3baea23f74f69d51f0c06c2e2082d0d9c28b0733a4c2",
- "sha256:2b69cf4b0fa2716fd977aa4e1fd39af6110eb47b2bb30b4e5a469d8fbecfc102",
- "sha256:2e952fa17ba48cbc2dc063ddeec37d7dc4ea0ef7db0ac1eda8906365a8543f31",
- "sha256:348b49dd737ff74cfb5e663e18cb069b44c64f77ec0523b5794efafbfa7df0b8",
- "sha256:3d72a5fdc5f00ca85160915eb9a973cf9a0ab8148f6eda40708bf672c55ac1d1",
- "sha256:4957452f7868f43f32c090dadb4188e9c74a4687323c87a882e943c2bd4780c3",
- "sha256:5138cec2ee1e53a671e11cc519505eb08aaaaf390c508f25b09605763d48de4b",
- "sha256:587098ca4fc46c95736459d171102336af12f0d415b3b865972a79c03f06259f",
- "sha256:5b79368bcdb1da4a05f931b62760bea0955ee2c81531d8e84625df2defd3f709",
- "sha256:5cf43807392247d9bc99737160da32d3fa619e0bfd85ba24d1c78db205f472a4",
- "sha256:676d1a80b1eebc0cacae8dd09b2fde24213173bf65650d22b038c5ed4039f392",
- "sha256:6b0211ecda389101a7d1d3df2eba0cf7ffbdd2480ca6f1d2257c7bd739e84110",
- "sha256:79cde4660de6f0bb523c229763bd8ad9a93ac6760b72c369cf1213955c430934",
- "sha256:7aba9786ac32c2a6d5fb446002ed936b47d5e1f10c466ef7e48f66eb9f9ebe3b",
- "sha256:7c8159352244e11bdd422226aa17651110b600d175220c451a9acf795e7414e0",
- "sha256:945f2eedf4fc6b2432697eb90bb98cc467de5147869e57405bfc31fa0b824741",
- "sha256:96b4e902cde37a7fc6ab306b3ac089a3949e6ce3d824eeca5b19dc0bedb9f6e2",
- "sha256:9a7bccb1212e63f309eb9fab47b6eaef796f59850f169a25695b248ca1bf681b",
- "sha256:a3bfcac727538ec11af304b5eccadbac952d4cca1a551a29b8fe554e3ad535dc",
- "sha256:b19e9f1b85c5d6136f5a0549abdc55dcbd63aba18b4f10d0d063eb65ef2c68b4",
- "sha256:b664011bb14ca1f2287c17185e222f2098f7b4c857961dbcf9badb28786dbbf4",
- "sha256:bde7959ef012b628868d69c474ec4920252656d0800835ed999ba5e4f57e3e2e",
- "sha256:cb095a0657d792c8de9f7c9a0452385a309dfb1bbbb3357d6b1e216353ade6ca",
- "sha256:d16d42a1b9772152c1fe606f679b2316551f7e1a1ce273e7f808e82a136cdb3d",
- "sha256:d444b1545430ffc1e7a24ce5a9be122ccd3b135a7b7e695c5862c5aff0b11159",
- "sha256:d93ccc7bf409ec0a23f2ac70977507e0b8a8d8c54e5ee46109af2f0ec9e411f3",
- "sha256:df6444f952ca849016902662e1a47abf4fa0678d75f92fd9dd27f20525f809cd",
- "sha256:e63850d8c52ba2b502662bf3c02603175c2397a9acc756090e444ce49508d41e",
- "sha256:ec43358c105794bc2b6fd34c68d27f92bea7102393c01889e93f4b6a70975728",
- "sha256:f4c6926d9c03dadce7a3b378b40d2fea912c1344ef9b29869f984fb3d2a2420b"
- ],
- "index": "pypi",
- "version": "==2.7.7"
+ "sha256:007ca0df127b1862fc010125bc4100b7a630efc6841047bd11afceadb4754611",
+ "sha256:03c49e02adf0b4d68f422fdbd98f7a7c547beb27e99a75ed02298f85cb48406a",
+ "sha256:0a1232cdd314e08848825edda06600455ad2a7adaa463ebfb12ece2d09f3370e",
+ "sha256:131c80d0958c89273d9720b9adf9df1d7600bb3120e16019a7389ab15b079af5",
+ "sha256:2de34cc3b775724623f86617d2601308083176a495f5b2efc2bbb0da154f483a",
+ "sha256:2eddc31500f73544a2a54123d4c4b249c3c711d31e64deddb0890982ea37397a",
+ "sha256:484f6c62bdc166ee0e5be3aa831120423bf399786d1f3b0304526c86180fbc0b",
+ "sha256:4c2d9369ed40b4a44a8ccd6bc3a7db6272b8314812d2d1091f95c4c836d92e06",
+ "sha256:70f570b5fa44413b9f30dbc053d17ef3ce6a4100147a10822f8662e58d473656",
+ "sha256:7a2b5b095f3bd733aab101c89c0e1a3f0dfb4ebdc26f6374805c086ffe29d5b2",
+ "sha256:804914a669186e2843c1f7fbe12b55aad1b36d40a28274abe6027deffad9433d",
+ "sha256:8520c03172da18345d012949a53617a963e0191ccb3c666f23276d5326af27b5",
+ "sha256:90da901fc33ea393fc644607e4a3916b509387e9339ec6ebc7bfded45b7a0ae9",
+ "sha256:a582416ad123291a82c300d1d872bdc4136d69ad0b41d57dc5ca3df7ef8e3088",
+ "sha256:ac8c5e20309f4989c296d62cac20ee456b69c41fd1bc03829e27de23b6fa9dd0",
+ "sha256:b2cf82f55a619879f8557fdaae5cec7a294fac815e0087c4f67026fdf5259844",
+ "sha256:b59d6f8cfca2983d8fdbe457bf95d2192f7b7efdb2b483bf5fa4e8981b04e8b2",
+ "sha256:be08168197021d669b9964bd87628fa88f910b1be31e7010901070f2540c05fd",
+ "sha256:be0f952f1c365061041bad16e27e224e29615d4eb1fb5b7e7760a1d3d12b90b6",
+ "sha256:c1c9a33e46d7c12b9c96cf2d4349d783e3127163fd96254dcd44663cf0a1d438",
+ "sha256:d18c89957ac57dd2a2724ecfe9a759912d776f96ecabba23acb9ecbf5c731035",
+ "sha256:d7e7b0ff21f39433c50397e60bf0995d078802c591ca3b8d99857ea18a7496ee",
+ "sha256:da0929b2bf0d1f365345e5eb940d8713c1d516312e010135b14402e2a3d2404d",
+ "sha256:de24a4962e361c512d3e528ded6c7480eab24c655b8ca1f0b761d3b3650d2f07",
+ "sha256:e45f93ff3f7dae2202248cf413a87aeb330821bf76998b3cf374eda2fc893dd7",
+ "sha256:f046aeae1f7a845041b8661bb7a52449202b6c5d3fb59eb4724e7ca088811904",
+ "sha256:f1dc2b7b2748084b890f5d05b65a47cd03188824890e9a60818721fd492249fb",
+ "sha256:fcbe7cf3a786572b73d2cd5f34ed452a5f5fac47c9c9d1e0642c457a148f9f88"
+ ],
+ "index": "pypi",
+ "version": "==2.8.2"
},
"pycparser": {
"hashes": [
@@ -1337,10 +1335,10 @@
},
"pdbpp": {
"hashes": [
- "sha256:3936ed6c145d9bebad9f532a20796d7022fc251ad6b041adc56b67839efd5173"
+ "sha256:ee7eab02ecf32d92bd66b45eedb9bda152fa13f7be0dceb7050413a52cbbc4dd"
],
"index": "pypi",
- "version": "==0.9.15"
+ "version": "==0.10.0"
},
"pexpect": {
"hashes": [
From f980debb6d322e047a349e03477a5d7ecd9f1653 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Tue, 23 Apr 2019 14:27:37 -0400
Subject: [PATCH 64/79] 10968 fix sentry logging
---
src/etools/config/sentry.py | 22 ----------------------
src/etools/config/settings/base.py | 23 +++++++++++++++++++++++
src/etools/config/settings/production.py | 3 ---
3 files changed, 23 insertions(+), 25 deletions(-)
delete mode 100644 src/etools/config/sentry.py
diff --git a/src/etools/config/sentry.py b/src/etools/config/sentry.py
deleted file mode 100644
index a7f92dd158..0000000000
--- a/src/etools/config/sentry.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from django.conf import settings
-from django.db import connection
-
-import sentry_sdk
-from sentry_sdk import configure_scope
-from sentry_sdk.integrations.celery import CeleryIntegration
-from sentry_sdk.integrations.django import DjangoIntegration
-
-if hasattr(settings, 'SENTRY_DSN'):
- def before_send(event, hint):
- with configure_scope() as scope:
- scope.set_extra("tenant", connection.tenant.schema_name)
-
- return event
-
- sentry_sdk.init(
- dsn=settings.SENTRY_DSN,
- # by default this is False, must be set to True so the library attaches the request data to the event
- send_default_pii=True,
- integrations=[DjangoIntegration(), CeleryIntegration()],
- before_send=before_send,
- )
diff --git a/src/etools/config/settings/base.py b/src/etools/config/settings/base.py
index 744d430b5d..7435cad390 100644
--- a/src/etools/config/settings/base.py
+++ b/src/etools/config/settings/base.py
@@ -17,8 +17,14 @@
import os
from os.path import abspath, basename, dirname, join, normpath
+from django.db import connection
+
import dj_database_url
+import sentry_sdk
import yaml
+from sentry_sdk import configure_scope
+from sentry_sdk.integrations.celery import CeleryIntegration
+from sentry_sdk.integrations.django import DjangoIntegration
import etools
@@ -424,6 +430,23 @@ def get_from_secrets_or_env(var_name, default=None):
'JWT_AUTH_HEADER_PREFIX': 'JWT',
}
+SENTRY_DSN = get_from_secrets_or_env('SENTRY_DSN') # noqa: F405
+
+if SENTRY_DSN:
+ def before_send(event, hint):
+ with configure_scope() as scope:
+ scope.set_extra("tenant", connection.tenant.schema_name)
+
+ return event
+
+ sentry_sdk.init(
+ dsn=SENTRY_DSN,
+ # by default this is False, must be set to True so the library attaches the request data to the event
+ send_default_pii=True,
+ integrations=[DjangoIntegration(), CeleryIntegration()],
+ before_send=before_send,
+ )
+
# eTools settings ################################
diff --git a/src/etools/config/settings/production.py b/src/etools/config/settings/production.py
index a9ecbcba0d..4bfe367c90 100644
--- a/src/etools/config/settings/production.py
+++ b/src/etools/config/settings/production.py
@@ -5,9 +5,6 @@
from etools.config.settings.base import * # noqa: F403
-# sentry-sdk: https://github.com/getsentry/sentry-python
-SENTRY_DSN = get_from_secrets_or_env('SENTRY_DSN'), # noqa: F405
-
# Security settings for production
ALLOWED_HOSTS = [
# Nope, regular expressions are not supported for this setting
From addce56b10ba3427a04ee582f7cd2f63f59e3376 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Tue, 23 Apr 2019 15:00:47 -0400
Subject: [PATCH 65/79] country_available_for_new_countries
---
.../users/management/commands/add_country.py | 3 ++
.../migrations/0010_auto_20190423_1920.py | 28 +++++++++++++++++++
src/etools/applications/users/models.py | 6 ++--
3 files changed, 34 insertions(+), 3 deletions(-)
create mode 100644 src/etools/applications/users/migrations/0010_auto_20190423_1920.py
diff --git a/src/etools/applications/users/management/commands/add_country.py b/src/etools/applications/users/management/commands/add_country.py
index 9600b6161e..ac6ffdf768 100644
--- a/src/etools/applications/users/management/commands/add_country.py
+++ b/src/etools/applications/users/management/commands/add_country.py
@@ -1,3 +1,4 @@
+from django.contrib.auth import get_user_model
from django.core.management import call_command
from django.core.management.base import BaseCommand, CommandError
from django.db import connection
@@ -30,5 +31,7 @@ def handle(self, *args, **options):
connection.set_schema(slug)
call_command('loaddata', 'attachments_file_types')
call_command('loaddata', 'audit_risks_blueprints')
+ for user in get_user_model().objects.filter(is_superuser=True):
+ user.profile.countries_available.add(country)
except Exception as exp:
raise CommandError(*exp.args)
diff --git a/src/etools/applications/users/migrations/0010_auto_20190423_1920.py b/src/etools/applications/users/migrations/0010_auto_20190423_1920.py
new file mode 100644
index 0000000000..292f3b3f8d
--- /dev/null
+++ b/src/etools/applications/users/migrations/0010_auto_20190423_1920.py
@@ -0,0 +1,28 @@
+# Generated by Django 2.1.8 on 2019-04-23 19:20
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0009_auto_20190122_1412'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='country',
+ name='offices',
+ field=models.ManyToManyField(blank=True, related_name='offices', to='users.Office', verbose_name='Offices'),
+ ),
+ migrations.AlterField(
+ model_name='country',
+ name='threshold_tae_usd',
+ field=models.DecimalField(blank=True, decimal_places=4, max_digits=20, null=True, verbose_name='Threshold TAE (USD)'),
+ ),
+ migrations.AlterField(
+ model_name='country',
+ name='threshold_tre_usd',
+ field=models.DecimalField(blank=True, decimal_places=4, max_digits=20, null=True, verbose_name='Threshold TRE (USD)'),
+ ),
+ ]
diff --git a/src/etools/applications/users/models.py b/src/etools/applications/users/models.py
index 052c50c40b..96be817b30 100644
--- a/src/etools/applications/users/models.py
+++ b/src/etools/applications/users/models.py
@@ -109,11 +109,11 @@ class Country(TenantMixin):
blank=True)
# TODO: rename the related name as it's inappropriate for relating offices to countries.. should be office_countries
- offices = models.ManyToManyField('Office', related_name='offices', verbose_name=_('Offices'))
+ offices = models.ManyToManyField('Office', related_name='offices', verbose_name=_('Offices'), blank=True)
- threshold_tre_usd = models.DecimalField(max_digits=20, decimal_places=4, default=None, null=True,
+ threshold_tre_usd = models.DecimalField(max_digits=20, decimal_places=4, blank=True, null=True,
verbose_name=_('Threshold TRE (USD)'))
- threshold_tae_usd = models.DecimalField(max_digits=20, decimal_places=4, default=None, null=True,
+ threshold_tae_usd = models.DecimalField(max_digits=20, decimal_places=4, blank=True, null=True,
verbose_name=_('Threshold TAE (USD)'))
def __str__(self):
From f59ebe3ca3d5099188b2358045967ee334e6e6a4 Mon Sep 17 00:00:00 2001
From: Greg Reinbach
Date: Wed, 24 Apr 2019 09:15:57 -0400
Subject: [PATCH 66/79] Add specific date requirement check on traevl
activities
---
.../applications/t2f/serializers/travel.py | 4 ++++
.../t2f/tests/test_travel_details.py | 17 +++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/src/etools/applications/t2f/serializers/travel.py b/src/etools/applications/t2f/serializers/travel.py
index fa07974aeb..9795d893a2 100644
--- a/src/etools/applications/t2f/serializers/travel.py
+++ b/src/etools/applications/t2f/serializers/travel.py
@@ -106,6 +106,10 @@ def validate(self, attrs):
if not attrs.get('is_primary_traveler'):
if not attrs.get('primary_traveler'):
raise ValidationError({'primary_traveler': serializers.Field.default_error_messages['required']})
+ if not attrs.get('date'):
+ raise ValidationError({
+ 'date': serializers.Field.default_error_messages['required']
+ })
partner = attrs.get('partner', getattr(self.instance, 'partner', None))
travel_type = attrs.get('travel_type', getattr(self.instance, 'travel_type', None))
diff --git a/src/etools/applications/t2f/tests/test_travel_details.py b/src/etools/applications/t2f/tests/test_travel_details.py
index 491d845b36..7c378aa389 100644
--- a/src/etools/applications/t2f/tests/test_travel_details.py
+++ b/src/etools/applications/t2f/tests/test_travel_details.py
@@ -283,6 +283,23 @@ def test_activity_location(self):
self.assertCountEqual(response_json['activities'][0]['locations'], [location.id, location_2.id])
self.assertEqual(response_json['activities'][1]['locations'], [location_3.id])
+ def test_activity_patch_no_date(self):
+ data = {
+ 'activities': [{'is_primary_traveler': True}],
+ 'traveler': self.traveler.pk,
+ }
+ response = self.forced_auth_req(
+ 'patch',
+ reverse('t2f:travels:details:index', args=[self.travel.pk]),
+ data=data,
+ user=self.traveler,
+ )
+ response_json = json.loads(response.rendered_content)
+ self.assertEqual(
+ response_json,
+ {'activities': [{'date': ['This field is required.']}]},
+ )
+
def test_activity_results(self):
location = LocationFactory()
location_2 = LocationFactory()
From a8d2c04a2fa00eec4d2ab48a6754757542822801 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Wed, 24 Apr 2019 10:13:36 -0400
Subject: [PATCH 67/79] 10666 tpm export
---
src/etools/applications/tpm/views.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/etools/applications/tpm/views.py b/src/etools/applications/tpm/views.py
index 30be67df70..e81b87c45c 100644
--- a/src/etools/applications/tpm/views.py
+++ b/src/etools/applications/tpm/views.py
@@ -409,7 +409,7 @@ def get_obj_permission_context(self, obj):
@action(detail=False, methods=['get'], url_path='activities/export', renderer_classes=(TPMActivityCSVRenderer,))
def activities_export(self, request, *args, **kwargs):
tpm_activities = TPMActivity.objects.filter(
- tpm_visit__in=self.get_queryset(),
+ tpm_visit__in=self.filter_queryset(self.get_queryset()),
).prefetch_related(
'tpm_visit', 'section', 'locations', 'cp_output'
).order_by('tpm_visit', 'id')
@@ -421,7 +421,7 @@ def activities_export(self, request, *args, **kwargs):
@action(detail=False, methods=['get'], url_path='locations/export', renderer_classes=(TPMLocationCSVRenderer,))
def locations_export(self, request, *args, **kwargs):
tpm_locations = TPMActivity.locations.through.objects.filter(
- activity__in=self.get_queryset().values_list('tpm_activities__id', flat=True),
+ activity__in=self.filter_queryset(self.get_queryset()).values_list('tpm_activities__id', flat=True),
).prefetch_related(
'activity', 'location', 'activity__tpmactivity__tpm_visit', 'activity__tpmactivity__section',
'activity__cp_output'
From 29df3dde673afb9de9c19587d51ccca2ef202bf7 Mon Sep 17 00:00:00 2001
From: Domenico DiNicola
Date: Thu, 25 Apr 2019 09:37:23 -0400
Subject: [PATCH 68/79] Merge pull request #60 from unicef/staging
Staging
Merge pull request #60 from unicef/staging
Staging
Merge pull request #60 from unicef/staging
Staging
restored template
---
src/etools/templates/login_base.html | 71 +++++++++++++++++++++
src/etools/templates/no_country_found.html | 45 ++-----------
src/etools/templates/removed_workspace.html | 54 ++++------------
3 files changed, 91 insertions(+), 79 deletions(-)
create mode 100644 src/etools/templates/login_base.html
diff --git a/src/etools/templates/login_base.html b/src/etools/templates/login_base.html
new file mode 100644
index 0000000000..d88da6c9d2
--- /dev/null
+++ b/src/etools/templates/login_base.html
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+ UNICEF eTools
+
+
+
+
+{% block extra_head %}
+
+
+
+
+ {% endblock %}
+
+
+
+
+ {% block toolbar %}
+ {% endblock toolbar %}
+
+
+ {% block content %}
+ {% endblock content %}
+ {% block extra_js %}
+ {% endblock %}
+
+
+
diff --git a/src/etools/templates/no_country_found.html b/src/etools/templates/no_country_found.html
index d460ca8ad6..b17fae1c10 100644
--- a/src/etools/templates/no_country_found.html
+++ b/src/etools/templates/no_country_found.html
@@ -1,53 +1,22 @@
{% extends "login_base.html" %}
-
-{% block extra_head %}
-
-
-
-
- {% endblock %}
{% block toolbar %}
-
-
-
Country workspace not found on user
-
+
+
+
Country workspace not found on user
+
{% endblock toolbar %}
{% block content %}
Hi {{ user }},
- Your user profile does not have a country workspace associated with it...
+ Your user profile does not have a country workspace associated with it.
Please contact the eTools focal point within your organization to help you gain access.